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的使用:
随机推荐
- 深入学习jQuery事件对象
× 目录 [1]获取 [2]事件类型 [3]事件目标[4]当前元素[5]事件冒泡[6]默认行为[7]命名空间[8]返回值[9]键值 前面的话 在触发DOM上的某个事件时,会产生一个事件对象event, ...
- poj 3630 Phone List
#include<iostream> #include<cstdio> #include<cstring> #define N 100005 using names ...
- Web APi之过滤器执行过程原理解析【二】(十一)
前言 上一节我们详细讲解了过滤器的创建过程以及粗略的介绍了五种过滤器,用此五种过滤器对实现对执行Action方法各个时期的拦截非常重要.这一节我们简单将讲述在Action方法上.控制器上.全局上以及授 ...
- 基于Metronic的Bootstrap开发框架经验总结(5)--Bootstrap文件上传插件File Input的使用
Bootstrap文件上传插件File Input是一个不错的文件上传控件,但是搜索使用到的案例不多,使用的时候,也是一步一个脚印一样摸着石头过河,这个控件在界面呈现上,叫我之前使用过的Uploadi ...
- 学习总结之 WebApi 用户登录和匿名登录,及权限验证
近些天,看了一些博客园大牛关于webApi项目的的文章,也有请教师兄一些问题,自己做了个Demo试了试,收获甚多.感谢感谢,下面是我一些学习的总结,如若有错的地方请多多指教!! WebApi登陆与身份 ...
- jQuery的事件模型
前几天自己着重读了jQuery1.11.1的源码,又结合了之前对DE事件模型的分析,最后也实现一个简陋的事件模型. jQuery的事件系统离不开jQuery的缓存系统. jQuery的第一代缓存是直接 ...
- DotNet隐藏敏感信息操作方法
在项目中,有时候一些信息不便完全显示,只需要显示部分信息.现在提供一些隐藏敏感信息的操作方法,主要为对信息的截取操作: 1.指定左右字符数量,中间的*的个数和实际长度有关: /// <summa ...
- Android从网络某个地址下载文件、写入SD卡
首先创建一个HttpDownloader类,获取下载文件的网络地址,将文件下载下来以String流的方式返回: public String download(String urlStr){ //url ...
- 1.JAVA中使用JNI调用C++代码学习笔记
Java 之JNI编程1.什么是JNI? JNI:(Java Natibe Inetrface)缩写. 2.为什么要学习JNI? Java 是跨平台的语言,但是在有些时候仍然是有需要调用本地代码 ( ...
- MVC学习系列14--Bundling And Minification【捆绑和压缩】--翻译国外大牛的文章
这个系列是,基础学习系列的最后一部分,这里,我打算翻译一篇国外的技术文章结束这个基础部分的学习:后面打算继续写深入学习MVC系列的文章,之所以要写博客,我个人觉得,做技术的,首先得要懂得分享,说不定你 ...