POI(Point Of Interest),感興趣點,其實呢,嚴格意義上說應該不是POI,但是單位就這樣叫了,我也就這樣叫了,其實現的功能大致是這樣的:用過百度地圖的朋友們都知道你在百度地圖時,當鼠標經過某個點時會顯示這個對象的名稱,點擊該對象,會彈出該對象的詳細信息。如下圖所示:
實現後的效果呢就是這樣子的,下面呢我來說說在Arcgis Server for JavaScript API下,我實現該效果的思路與想法。
首先,得有一個圖層用於顯示這些點對象,這個圖層可以是切片,也可以是WMS,也可以是featurelayer,反正只要是能將這些東西在地圖上顯示出來就Ok了。
map = new Map("map",{ logo:false, center: [106.6854, 35.8364], slider: true });
var tiledLayer = new Tiled(tiledUrl); map.addLayer(tiledLayer);
接下來說說這些點究竟是怎麼回事,其實呢,這些點呢就是一個JSON格式的數據,裏面的每一個對象包含了該對象的屬性信息,返回的JSON格式的大概如下:
{ total:3, layerpoi:[ {poiCode:'0',poiTitle:'wlmq',poix:9748157.53561782,poiy:5429353.112666599 }, {poiCode:'1',poiTitle:'hhht',poix:12453416.840686005,poiy:4997253.113785474 }, {poiCode:'2',poiTitle:'lz',poix:11528834.54654876,poiy:4319715.295065851 } ] }
注意,每一個對象必須得有一個id,name,x,y,前面這四個是必須的,其他的可有可無,至於說怎麼返回,這個事情你自己考慮,怎麼方便怎麼來,asp.net可以用*.ashx,java可以考慮servlet或者別的,反正能返回這個JSON就Ok。那麼,我何時請求讓他返回呢,有兩個時間:1、地圖初始化加載的時候;2、地圖的extent發生變化的時候。我們可以用ajax來實現:
function excuteData(dataUrl){ $.ajax({ type: "post", dataType: "JSON", url: dataUrl, data: {level: mapLevel, bbox: bbox}, success: function(json){ var data = json.layerpoi; total=json.total; if(total!=0){ for(var i in data){ var xmin,ymin,xmax,ymax; xmin=data[i].poix-offset; ymin=data[i].poiy-offset; xmax=data[i].poix+offset; ymax=data[i].poiy+offset; var poiExtent = new esri.geometry.Extent(xmin,ymin,xmax,ymax,map.spatialReference); poiArray[i] = new POI(data[i].poiType,data[i].poiTitle,data[i].poix,data[i].poiy,poiExtent); } } } }); }
分析上面的代碼,ajax請求,傳遞的參數爲level(地圖的級別),bbox(地圖當前的四至),意思就是通過當前地圖的級別和四至判斷當前可是範圍內所包含的點對象的個數與信息,success後返回JSON,首先,判斷total的個數是否爲0,不爲0,說明有點對象,這時,根據地圖的比例尺計算一個合理的offset,根據x、y、offset給每一個點對象創建一個extent,你可以建一個對象類將這些對象點的信息存儲起來:
function POI(code,title,x,y,extent){ this.code=code; this.title=title; this.x=x; this.y=y; this.extent=extent; }
接着,實現移動鼠標去判斷鼠標當前所在點是否被對象點所包含,包含了,顯示該對象的信息,並高亮顯示給對象:
//鼠標移動事件 function mapMouseMove(evt){ var point = evt.mapPoint; for(var i = 0; i < poiArray.length; i++){ var extent=poiArray[i].extent; if(extent.contains(point)){ console.log("true"); poipoint = new esri.geometry.Point([poiArray[i].x,poiArray[i].y],map.spatialReference); var graphicMarker = new esri.Graphic(poipoint, pmsHover); map.graphics.add(graphicMarker); var font = new esri.symbol.Font(); font.setSize("10pt"); font.setFamily("微軟雅黑"); var text = new esri.symbol.TextSymbol(poiArray[i].title); text.setFont(font); text.setColor(new dojo.Color([0,0,0,100])); text.setOffset(15,-20); var graphicLabel = new esri.Graphic(poipoint,text); map.graphics.add(graphicLabel); flag=i;
break; } else{ console.log("false"); map.graphics.clear(); flag=null; } } } map.on("mouse-move",mapMouseMove);
給地圖添加鼠標移動事件,當移動到對象出現對象名稱時,點擊該對象,出現對象的詳細信息,所以給地圖添加click事件:
function mapClick(evt){ if(flag==null){ return; } else{ map.centerAt(poipoint); map.infoWindow.setTitle(poiArray[flag].title); map.infoWindow.setContent("類型:"+poiArray[flag].type +"<br>X:"+poiArray[flag].x +"<br>Y:"+poiArray[flag].y); map.infoWindow.show(poipoint); } } map.on("click",mapClick);
上面說了,請求返回JSON數據的時間有倆,所以還得給地圖添加extent-change事件:
function extentChange(evt){ mapLevel=map.getLevel(); bbox=this.map.extent.xmin+","+this.map.extent.ymin+","+this.map.extent.xmax+","+this.map.extent.ymax; excuteData(dataUrl); } map.on("extent-change",extentChange);
這樣,我所要的功能就基本上實現了,效果如下:
初始狀態
鼠標經過時顯示該對象的名稱並高亮顯示
單擊時顯示該對象的詳細信息