1.開篇
守望屁股實在太好玩了,所以最近有點懶,這次就先寫個簡單的來湊一下數。這次我的模仿目標是天地圖的地圖聯動。
天地的地圖聯動不僅地圖有聯動,而且鼠標也有聯動,我就照着這個目標進行山寨。
2.准備
地圖聯動其實就是當一張的extent發生了變化,另一張圖的extent也要同步變化,這樣就可以兩張圖的范圍同步了。同理,這樣就可以擴展到N張圖進行聯動。所以這次的目標就是實現添加任意的地圖都要可以聯動。首先依然是先看一下官方文檔。找到有用的方法或者事件。
整體的難點在於如何判斷主地圖(有鼠標動作的地圖),通過官方文檔,我們可以利用mouse-over事件來進行主地圖的判斷,在添加地圖時,監聽每張地圖的mouse-over事件。
3.開始山寨

1 //添加地圖,相互聯動 2 addMap: function (map) { 3 var self = this; 4 if (this._maps.indexOf(map) != -1)return;//如果已經在聯動地圖集合就不添加 5 var graphicLayer=new GraphicLayer({id:"mapLinkagerLayer"}); 6 var mouseHandler= map.on("mouse-over", function (evt) {//鼠標在哪個地圖上,該地圖就是激活地圖 7 self.activeMap = map; 8 self. _clearActiveMapEvents(); 9 self._bindActiveMapEvents(); 10 }); 11 12 var graphic=new Graphic(); 13 graphic.setSymbol(this.mouseSymbol); 14 map.addLayer(graphicLayer); 15 graphicLayer.add(graphic) 16 17 this._maps.push(map); 18 this._mapMouseOverEventHandlers.push(mouseHandler); 19 this._mouseGraphicLayers.push(graphicLayer); 20 this._mouseGraphics.push(graphic); 21 }, 22
這里self. _clearActiveMapEvents()就是清除上一個主地圖的相關事件;在清除上一個的事件后利用self._bindActiveMapEvents()對當前地圖進行事件的綁定。這兩個方法的具體內容我會在后面詳細介紹。graphicLayer就是為了實現鼠標聯動。

1 //清除當前地圖聯動事件 2 _clearActiveMapEvents: function () { 3 this._activeMapEventHandlers.forEach(function (eventHandler) { 4 eventHandler.remove(); 5 }); 6 this._activeMapEventHandlers = []; 7 },
這里我們先清除上一個主地圖的所有事件,我把這些事件都放到this._activeMapEventHandlers集合中。

1 //為當前地圖添加聯動 2 _bindActiveMapEvents: function () { 3 var self = this; 4 //放大聯動 5 this._activeMapEventHandlers.push(this.activeMap.on("zoom-end", function (evt) { 6 self._maps.forEach(function (map) { 7 if (map != self.activeMap) { 8 map.setExtent(evt.extent); 9 } 10 }); 11 })); 12 //平移聯動 13 this._activeMapEventHandlers.push(this.activeMap.on("pan-end", function (evt) { 14 self._maps.forEach(function (map) { 15 if (map != self.activeMap) { 16 map.setExtent(evt.extent); 17 } 18 }); 19 })); 20 21 //鼠標聯動 22 this._activeMapEventHandlers.push(this.activeMap.on("mouse-move", function (evt) { 23 self._maps.forEach(function (map) { 24 var idx = self._maps.indexOf(map); 25 var graphicLayer=map.getLayer("mapLinkagerLayer") 26 var graphic=self._mouseGraphics[idx]; 27 if (map != self.activeMap) { 28 graphicLayer.show(); 29 graphic.setGeometry(evt.mapPoint); 30 }else{ 31 graphicLayer.hide();//激活地圖不顯示聯動鼠標 32 } 33 }); 34 })); 35 } 36 });
在主地圖平移和放大后,通過遍歷_maps 集合,並利用事件提供的extent參數和map.setExtent()方法來設置地圖的聯動。鼠標的聯動則是通過監聽mouse-move事件,獲取事件中的mapPoint參數來進行鼠標Graphic的定位。至此核心的部分已經全部完成了。
源碼:

1 /** 2 * Created by Extra
3 * 地圖聯動輔助類 4 * version:v1.0.0 5 */ 6 define("dextra/modules/MapLinkager", [ 7 "dojo/_base/declare", 8 "esri/layers/GraphicsLayer", 9 "esri/graphic", 10 "esri/symbols/SimpleMarkerSymbol" 11 ], function ( declare,GraphicLayer,Graphic,SimpleMarkerSymbol) { 12 var maplinkager = declare(null, { 13 declaredClass: "dextra.modules.MapLinkager", 14 _maps: null,//參與聯動的地圖控件集合 15 _activeMapEventHandlers: null,//當前鼠標所在地圖事件集合 16 _mapMouseOverEventHandlers:null,//所有地圖mouse-over事件集合 17 _mouseGraphicLayers:null,//鼠標聯動GraphicLayer 18 activeMap: null,//當前激活地圖 19 mouseSymbol:null,//鼠標樣式 20 _mouseGraphics:null,//鼠標Graphic集合 21 22 constructor: function () { 23 this._maps = []; 24 this._activeMapEventHandlers=[]; 25 this._mapMouseOverEventHandlers=[]; 26 this._mouseGraphicLayers=[]; 27 this.mouseSymbol=new SimpleMarkerSymbol({ 28 "color": [255,0,0], 29 "size": 10, 30 "xoffset": 0, 31 "yoffset": 0, 32 "type": "esriSMS", 33 "style": "esriSMSCircle", 34 "outline": { 35 "color": [255,0,0], 36 "width": 1, 37 "type": "esriSLS", 38 "style": "esriSLSSolid" 39 } 40 }); 41 this._mouseGraphics=[]; 42 43 }, 44 45 //添加地圖,相互聯動 46 addMap: function (map) { 47 var self = this; 48 if (this._maps.indexOf(map) != -1)return;//如果已經在聯動地圖集合就不添加 49 var graphicLayer=new GraphicLayer({id:"mapLinkagerLayer"}); 50 var mouseHandler= map.on("mouse-over", function (evt) {//鼠標在哪個地圖上,該地圖就是激活地圖 51 self.activeMap = map; 52 self. _clearActiveMapEvents(); 53 self._bindActiveMapEvents(); 54 }); 55 56 var graphic=new Graphic(); 57 graphic.setSymbol(this.mouseSymbol); 58 map.addLayer(graphicLayer); 59 graphicLayer.add(graphic) 60 61 this._maps.push(map); 62 this._mapMouseOverEventHandlers.push(mouseHandler); 63 this._mouseGraphicLayers.push(graphicLayer); 64 this._mouseGraphics.push(graphic); 65 }, 66 67 //移除地圖,取消聯動 68 removeMap: function (map) { 69 var idx = this._maps.indexOf(map); 70 this._maps.splice(idx, 1); 71 var graphicLayer= this._mouseGraphicLayers.splice(idx, 1)[0]; 72 graphicLayer.clear(); 73 map.removeLayer(graphicLayer); 74 75 this._mapMouseOverEventHandlers[idx].remove(); 76 this._mapMouseOverEventHandlers.splice(idx, 1); 77 this._mouseGraphics.splice(idx, 1); 78 this._clearActiveMapEvents(); 79 80 }, 81 82 //清除當前地圖聯動事件 83 _clearActiveMapEvents: function () { 84 this._activeMapEventHandlers.forEach(function (eventHandler) { 85 eventHandler.remove(); 86 }); 87 this._activeMapEventHandlers = []; 88 }, 89 90 //為當前地圖添加聯動 91 _bindActiveMapEvents: function () { 92 var self = this; 93 //放大聯動 94 this._activeMapEventHandlers.push(this.activeMap.on("zoom-end", function (evt) { 95 self._maps.forEach(function (map) { 96 if (map != self.activeMap) { 97 map.setExtent(evt.extent); 98 } 99 }); 100 })); 101 //平移聯動 102 this._activeMapEventHandlers.push(this.activeMap.on("pan-end", function (evt) { 103 self._maps.forEach(function (map) { 104 if (map != self.activeMap) { 105 map.setExtent(evt.extent); 106 } 107 }); 108 })); 109 110 //鼠標聯動 111 this._activeMapEventHandlers.push(this.activeMap.on("mouse-move", function (evt) { 112 self._maps.forEach(function (map) { 113 var idx = self._maps.indexOf(map); 114 var graphicLayer=map.getLayer("mapLinkagerLayer") 115 var graphic=self._mouseGraphics[idx]; 116 if (map != self.activeMap) { 117 graphicLayer.show(); 118 graphic.setGeometry(evt.mapPoint); 119 }else{ 120 graphicLayer.hide();//激活地圖不顯示聯動鼠標 121 } 122 }); 123 })); 124 } 125 }); 126 127 return maplinkager; 128 });
DEMO:

1 <!DOCTYPE html> 2 <html lang="en"> 3 <head> 4 <meta charset="UTF-8"> 5 <title>DExtra-HeatMap</title> 6 <link rel="stylesheet" href="https://js.arcgis.com/3.16/esri/css/esri.css"> 7 <style> 8 html, body, #map { 9 padding: 0; 10 margin: 0; 11 height: 100%; 12 } 13 </style> 14 <script> 15 var dojoConfig = { 16 parseOnLoad: true, 17 packages: [{ 18 name: 'custom', 19 location: location.pathname.replace(/\/[^/]+$/, '') + '/custom'//從cdn加載自己定義的模塊方法 20 }, 21 { 22 name: 'dextra', 23 location: '/extra.arcgis.3.x/dist/'//從cdn加載自己定義的模塊方法 24 }] 25 }; 26 console.log(location.pathname.replace(/\/[^/]+$/, '')); 27 </script> 28 29 <script src="https://js.arcgis.com/3.16/"></script> 30 31 <script> 32 require([ 33 "dojo/_base/array", 34 "dojo/on","dojo/dom", 35 "esri/map", 36 "esri/geometry/Point", 37 "dextra/layers/GoogleVectorLayer", 38 "dextra/layers/GoogleImageLayer", 39 "dextra/layers/GoogleTerrienLayer", 40 "dextra/modules/MapLinkager", 41 "dojo/domReady!"], function (array,on,dom,Map, Point, GoogleVectorLayer, GoogleImageLayer,GoogleTerrienLayer,MapLinkager) { 42 var map1 = new Map("map1", { 43 center: [102.8, 25.1], 44 zoom: 10, 45 }); 46 var googleVecLayer = new GoogleVectorLayer(); 47 map1.addLayer(googleVecLayer); 48 49 50 var map2 = new Map("map2", { 51 center: [102.8, 25.1], 52 zoom: 10, 53 }); 54 var googleimageLayer = new GoogleImageLayer(); 55 map2.addLayer(googleimageLayer); 56 57 var map3 = new Map("map3", { 58 center: [102.8, 25.1], 59 zoom: 10, 60 }); 61 var googleterrienLayer = new GoogleTerrienLayer(); 62 map3.addLayer(googleterrienLayer); 63 64 var mapLinker=new MapLinkager(); 65 mapLinker.addMap(map1); 66 mapLinker.addMap(map2); 67 mapLinker.addMap(map3); 68 69 70 on(dom.byId("btn1"),"click",function(evt){ 71 mapLinker.removeMap(map1); 72 }) 73 on(dom.byId("btn2"),"click",function(evt){ 74 mapLinker.removeMap(map2); 75 }) 76 77 on(dom.byId("btn3"),"click",function(evt){ 78 mapLinker.removeMap(map3); 79 }); 80 81 on(dom.byId("btn4"),"click",function(evt){ 82 mapLinker.addMap(map1); 83 }); 84 on(dom.byId("btn5"),"click",function(evt){ 85 mapLinker.addMap(map2); 86 }) 87 on(dom.byId("btn6"),"click",function(evt){ 88 mapLinker.addMap(map3); 89 }) 90 }); 91 92 93 </script> 94 </head> 95 <body> 96 <button id="btn1">Remove Map1</button> 97 <button id="btn2">Remove Map2</button> 98 <button id="btn3">Remove Map3</button> 99 100 <button id="btn4">Add Map1</button> 101 <button id="btn5">Add Map2</button> 102 <button id="btn6">Add Map3</button> 103 104 105 <div id="map1" style="width:49%;float:left"></div> 106 <div id="map2" style="width:49%; float:right"></div> 107 <div id="map3" style="width:49%; "></div> 108 </body> 109 </html>
有圖有真相:
demo的布局就請不要吐槽了。。。求放過。。。。
歡迎轉載 http://www.cnblogs.com/deliciousExtra/p/5600212.html