ArcGIS JS 学习笔记4 实现地图联动
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
ArcGIS JS 学习笔记4 实现地图联动的更多相关文章
- ArcGIS JS 学习笔记1 用ArcGIS JS 实现仿百度地图的距离量测和面积量测
一.开篇 在博客注册了三年,今天才决定写第一篇博客,警告自己不要懒!!! 二.关于ArcGIS JS 版本选择 在写这篇博客时ArcGIS JS 4.0正式版已经发布.它和3.x版本的不同是,Map不 ...
- ArcGIS JS 学习笔记3 实现百度风格的BubblePopup
1. 开篇 模仿是最好的学习,这次我们继续山寨百度,通过自定义Infowindow来实现百度风格的BubblePopup 2.准备 2.1 Copy模板 先打开百度地图,按下f12吧BubblePop ...
- ArcGIS JS 学习笔记2 实现仿百度的拖拽画圆
一.前言 吐槽一下,百度在国内除了百度地图是良心产品外,其他的真的不敢恭维.在上一篇笔记里,我已经实现了自定义的地图测量模块.在百度地图里面(其他地图)都有一个周边搜索的功能,拖拽画一个圆,然后以圆半 ...
- ArcGIS案例学习笔记2_1_山顶点提取最大值提取
ArcGIS案例学习笔记2_1_山顶点提取最大值提取 计划时间:第二天上午 目的:最大值提取 教程:Pdf page=343 数据:chap8/ex5/dem.tif 背景知识:等高线种类 基本等高线 ...
- ArcGIS案例学习笔记4_2
ArcGIS案例学习笔记4_2 联系方式:谢老师,135_4855_4328,xiexiaokui#qq.com 时间:第4天下午 案例1:批量水文分析地理建模 数据:实验数据\Chp11\tutor ...
- ArcGIS案例学习笔记1_1
ArcGIS案例学习笔记1_1 联系方式:谢老师,135_4855_4328, xiexiaokui#qq.com 时间:第一天上午 准备 0.U盘复制ArcGIS培训*** 1.练习数据不要放到桌面 ...
- ArcGIS案例学习笔记2_1
ArcGIS案例学习笔记2_1 联系方式:谢老师,135_4855_4328,xiexiaokui#qq.com 时间:第二天上午 案例1:学校选址 内容:栅格数据分析 教程:pdf page=323 ...
- js学习笔记:webpack基础入门(一)
之前听说过webpack,今天想正式的接触一下,先跟着webpack的官方用户指南走: 在这里有: 如何安装webpack 如何使用webpack 如何使用loader 如何使用webpack的开发者 ...
- Vue.js学习笔记(2)vue-router
vue中vue-router的使用:
随机推荐
- LINQ系列:Linq to Object量词操作符
量词操作符返回一个Boolean值,指示序列中是否存在部分或全部元素符号指定条件.LINQ中量词操作符包括:All.Any和Contains. 1. All All操作符判定在集合中是否所有的值都满足 ...
- Tomcat调优及JMX监控
Tomcat调优及JMX监控 实验背景 ====================================================== 系统版本:CentOS release 6.5 ( ...
- vue实例属性(vm.$els)
不需要表达式 参数: id(必需) 用法: 为 DOM 元素注册一个索引,方便通过所属实例的 $els 访问这个元素. 注意: 因为 HTML 不区分大小写,camelCase 名字比如 v-el:s ...
- Android音视频之MediaPlayer音视频播放
前言: 昨天总结了视频录制,今天来学习一下视频的播放,Android的视频播放主要采用MediaPlayer类. MediaPlayer介绍 MediaPlayer类可用于控制音频/视频文件或流的播放 ...
- 【读书笔记】XHTML与HTML5 的差异
最近在困惑html5和XHTML两者之间的具体区别,查看了百度.google和新浪等,他们首页的源码第一句都是 1 <!Doctype html> 这是HTML5的doctype声明,说明 ...
- 高级javascript---严格模式
严格模式 (JavaScript) 严格模式是一种将更好的错误检查引入代码中的方法. 在使用严格模式时,你无法使用隐式声明的变量.将值赋给只读属性或将属性添加到不可扩展的对象等. 本主题后面的代码 ...
- 构建自己的PHP框架--构建缓存组件(2)
上一篇博客中使用文件实现了缓存组件,这一篇我们就使用Redis来实现一下,剩下的如何使用memcache.mysql等去实现缓存我就不一一去做了. 首先我们需要安装一下 redis 和 phpredi ...
- 微服务实战(二):使用API Gateway--转
原文地址:http://dockone.io/article/482 [编者的话]本系列的第一篇介绍了微服务架构模式.它讨论了采用微服务的优点和缺点,除了一些复杂的微服务,这种模式还是复杂应用的理想选 ...
- swift 中数据类型那个的转换
在swift中关于数据类型的转换,如果参数是可选类型? 那么打印或者转换的结果 会带有Optional 字样,,
- iOS 如何设置导航的滑动返回手势, 和系统饿一样
iOS 7 滑动返回那些事儿 2014/05/17 Wei .entry-meta .entry-header 在智能机越来越普及,屏幕越做越大的当下,滑动返回手势已经成为了一个应用的标配功能,甚至可 ...