1.开篇
守望屁股实在太好玩了,所以最近有点懒,这次就先写个简单的来凑一下数。这次我的模仿目标是天地图的地图联动。
天地的地图联动不仅地图有联动,而且鼠标也有联动,我就照着这个目标进行山寨。
2.准备
地图联动其实就是当一张的extent发生了变化,另一张图的extent也要同步变化,这样就可以两张图的范围同步了。同理,这样就可以扩展到N张图进行联动。所以这次的目标就是实现添加任意的地图都要可以联动。首先依然是先看一下官方文档。找到有用的方法或者事件。
整体的难点在于如何判断主地图(有鼠标动作的地图),通过官方文档,我们可以利用mouse-over事件来进行主地图的判断,在添加地图时,监听每张地图的mouse-over事件。
3.开始山寨
//添加地图,相互联动
addMap: function (map) {
var self = this;
if (this._maps.indexOf(map) != -1)return;//如果已经在联动地图集合就不添加
var graphicLayer=new GraphicLayer({id:"mapLinkagerLayer"});
var mouseHandler= map.on("mouse-over", function (evt) {//鼠标在哪个地图上,该地图就是激活地图
self.activeMap = map;
self. _clearActiveMapEvents();
self._bindActiveMapEvents();
}); var graphic=new Graphic();
graphic.setSymbol(this.mouseSymbol);
map.addLayer(graphicLayer);
graphicLayer.add(graphic) this._maps.push(map);
this._mapMouseOverEventHandlers.push(mouseHandler);
this._mouseGraphicLayers.push(graphicLayer);
this._mouseGraphics.push(graphic);
},
这里self. _clearActiveMapEvents()就是清除上一个主地图的相关事件;在清除上一个的事件后利用self._bindActiveMapEvents()对当前地图进行事件的绑定。这两个方法的具体内容我会在后面详细介绍。graphicLayer就是为了实现鼠标联动。
//清除当前地图联动事件
_clearActiveMapEvents: function () {
this._activeMapEventHandlers.forEach(function (eventHandler) {
eventHandler.remove();
});
this._activeMapEventHandlers = [];
},
这里我们先清除上一个主地图的所有事件,我把这些事件都放到this._activeMapEventHandlers集合中。
//为当前地图添加联动
_bindActiveMapEvents: function () {
var self = this;
//放大联动
this._activeMapEventHandlers.push(this.activeMap.on("zoom-end", function (evt) {
self._maps.forEach(function (map) {
if (map != self.activeMap) {
map.setExtent(evt.extent);
}
});
}));
//平移联动
this._activeMapEventHandlers.push(this.activeMap.on("pan-end", function (evt) {
self._maps.forEach(function (map) {
if (map != self.activeMap) {
map.setExtent(evt.extent);
}
});
})); //鼠标联动
this._activeMapEventHandlers.push(this.activeMap.on("mouse-move", function (evt) {
self._maps.forEach(function (map) {
var idx = self._maps.indexOf(map);
var graphicLayer=map.getLayer("mapLinkagerLayer")
var graphic=self._mouseGraphics[idx];
if (map != self.activeMap) {
graphicLayer.show();
graphic.setGeometry(evt.mapPoint);
}else{
graphicLayer.hide();//激活地图不显示联动鼠标
}
});
}));
}
});
在主地图平移和放大后,通过遍历_maps 集合,并利用事件提供的extent参数和map.setExtent()方法来设置地图的联动。鼠标的联动则是通过监听mouse-move事件,获取事件中的mapPoint参数来进行鼠标Graphic的定位。至此核心的部分已经全部完成了。
源码:
/**
* Created by Extra
* 地图联动辅助类
* version:v1.0.0
*/
define("dextra/modules/MapLinkager", [
"dojo/_base/declare",
"esri/layers/GraphicsLayer",
"esri/graphic",
"esri/symbols/SimpleMarkerSymbol"
], function ( declare,GraphicLayer,Graphic,SimpleMarkerSymbol) {
var maplinkager = declare(null, {
declaredClass: "dextra.modules.MapLinkager",
_maps: null,//参与联动的地图控件集合
_activeMapEventHandlers: null,//当前鼠标所在地图事件集合
_mapMouseOverEventHandlers:null,//所有地图mouse-over事件集合
_mouseGraphicLayers:null,//鼠标联动GraphicLayer
activeMap: null,//当前激活地图
mouseSymbol:null,//鼠标样式
_mouseGraphics:null,//鼠标Graphic集合 constructor: function () {
this._maps = [];
this._activeMapEventHandlers=[];
this._mapMouseOverEventHandlers=[];
this._mouseGraphicLayers=[];
this.mouseSymbol=new SimpleMarkerSymbol({
"color": [255,0,0],
"size": 10,
"xoffset": 0,
"yoffset": 0,
"type": "esriSMS",
"style": "esriSMSCircle",
"outline": {
"color": [255,0,0],
"width": 1,
"type": "esriSLS",
"style": "esriSLSSolid"
}
});
this._mouseGraphics=[]; }, //添加地图,相互联动
addMap: function (map) {
var self = this;
if (this._maps.indexOf(map) != -1)return;//如果已经在联动地图集合就不添加
var graphicLayer=new GraphicLayer({id:"mapLinkagerLayer"});
var mouseHandler= map.on("mouse-over", function (evt) {//鼠标在哪个地图上,该地图就是激活地图
self.activeMap = map;
self. _clearActiveMapEvents();
self._bindActiveMapEvents();
}); var graphic=new Graphic();
graphic.setSymbol(this.mouseSymbol);
map.addLayer(graphicLayer);
graphicLayer.add(graphic) this._maps.push(map);
this._mapMouseOverEventHandlers.push(mouseHandler);
this._mouseGraphicLayers.push(graphicLayer);
this._mouseGraphics.push(graphic);
}, //移除地图,取消联动
removeMap: function (map) {
var idx = this._maps.indexOf(map);
this._maps.splice(idx, 1);
var graphicLayer= this._mouseGraphicLayers.splice(idx, 1)[0];
graphicLayer.clear();
map.removeLayer(graphicLayer); this._mapMouseOverEventHandlers[idx].remove();
this._mapMouseOverEventHandlers.splice(idx, 1);
this._mouseGraphics.splice(idx, 1);
this._clearActiveMapEvents(); }, //清除当前地图联动事件
_clearActiveMapEvents: function () {
this._activeMapEventHandlers.forEach(function (eventHandler) {
eventHandler.remove();
});
this._activeMapEventHandlers = [];
}, //为当前地图添加联动
_bindActiveMapEvents: function () {
var self = this;
//放大联动
this._activeMapEventHandlers.push(this.activeMap.on("zoom-end", function (evt) {
self._maps.forEach(function (map) {
if (map != self.activeMap) {
map.setExtent(evt.extent);
}
});
}));
//平移联动
this._activeMapEventHandlers.push(this.activeMap.on("pan-end", function (evt) {
self._maps.forEach(function (map) {
if (map != self.activeMap) {
map.setExtent(evt.extent);
}
});
})); //鼠标联动
this._activeMapEventHandlers.push(this.activeMap.on("mouse-move", function (evt) {
self._maps.forEach(function (map) {
var idx = self._maps.indexOf(map);
var graphicLayer=map.getLayer("mapLinkagerLayer")
var graphic=self._mouseGraphics[idx];
if (map != self.activeMap) {
graphicLayer.show();
graphic.setGeometry(evt.mapPoint);
}else{
graphicLayer.hide();//激活地图不显示联动鼠标
}
});
}));
}
}); return maplinkager;
});
DEMO:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>DExtra-HeatMap</title>
<link rel="stylesheet" href="https://js.arcgis.com/3.16/esri/css/esri.css">
<style>
html, body, #map {
padding: 0;
margin: 0;
height: 100%;
}
</style>
<script>
var dojoConfig = {
parseOnLoad: true,
packages: [{
name: 'custom',
location: location.pathname.replace(/\/[^/]+$/, '') + '/custom'//从cdn加载自己定义的模块方法
},
{
name: 'dextra',
location: '/extra.arcgis.3.x/dist/'//从cdn加载自己定义的模块方法
}]
};
console.log(location.pathname.replace(/\/[^/]+$/, ''));
</script> <script src="https://js.arcgis.com/3.16/"></script> <script>
require([
"dojo/_base/array",
"dojo/on","dojo/dom",
"esri/map",
"esri/geometry/Point",
"dextra/layers/GoogleVectorLayer",
"dextra/layers/GoogleImageLayer",
"dextra/layers/GoogleTerrienLayer",
"dextra/modules/MapLinkager",
"dojo/domReady!"], function (array,on,dom,Map, Point, GoogleVectorLayer, GoogleImageLayer,GoogleTerrienLayer,MapLinkager) {
var map1 = new Map("map1", {
center: [102.8, 25.1],
zoom: 10,
});
var googleVecLayer = new GoogleVectorLayer();
map1.addLayer(googleVecLayer); var map2 = new Map("map2", {
center: [102.8, 25.1],
zoom: 10,
});
var googleimageLayer = new GoogleImageLayer();
map2.addLayer(googleimageLayer); var map3 = new Map("map3", {
center: [102.8, 25.1],
zoom: 10,
});
var googleterrienLayer = new GoogleTerrienLayer();
map3.addLayer(googleterrienLayer); var mapLinker=new MapLinkager();
mapLinker.addMap(map1);
mapLinker.addMap(map2);
mapLinker.addMap(map3); on(dom.byId("btn1"),"click",function(evt){
mapLinker.removeMap(map1);
})
on(dom.byId("btn2"),"click",function(evt){
mapLinker.removeMap(map2);
}) on(dom.byId("btn3"),"click",function(evt){
mapLinker.removeMap(map3);
}); on(dom.byId("btn4"),"click",function(evt){
mapLinker.addMap(map1);
});
on(dom.byId("btn5"),"click",function(evt){
mapLinker.addMap(map2);
})
on(dom.byId("btn6"),"click",function(evt){
mapLinker.addMap(map3);
})
}); </script>
</head>
<body>
<button id="btn1">Remove Map1</button>
<button id="btn2">Remove Map2</button>
<button id="btn3">Remove Map3</button> <button id="btn4">Add Map1</button>
<button id="btn5">Add Map2</button>
<button id="btn6">Add Map3</button> <div id="map1" style="width:49%;float:left"></div>
<div id="map2" style="width:49%; float:right"></div>
<div id="map3" style="width:49%; "></div>
</body>
</html>
有图有真相:
demo的布局就请不要吐槽了。。。求放过。。。。
欢迎转载 http://www.cnblogs.com/deliciousExtra/p/5600212.html