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 实现地图联动的更多相关文章

  1. ArcGIS JS 学习笔记1 用ArcGIS JS 实现仿百度地图的距离量测和面积量测

    一.开篇 在博客注册了三年,今天才决定写第一篇博客,警告自己不要懒!!! 二.关于ArcGIS JS 版本选择 在写这篇博客时ArcGIS JS 4.0正式版已经发布.它和3.x版本的不同是,Map不 ...

  2. ArcGIS JS 学习笔记3 实现百度风格的BubblePopup

    1. 开篇 模仿是最好的学习,这次我们继续山寨百度,通过自定义Infowindow来实现百度风格的BubblePopup 2.准备 2.1 Copy模板 先打开百度地图,按下f12吧BubblePop ...

  3. ArcGIS JS 学习笔记2 实现仿百度的拖拽画圆

    一.前言 吐槽一下,百度在国内除了百度地图是良心产品外,其他的真的不敢恭维.在上一篇笔记里,我已经实现了自定义的地图测量模块.在百度地图里面(其他地图)都有一个周边搜索的功能,拖拽画一个圆,然后以圆半 ...

  4. ArcGIS案例学习笔记2_1_山顶点提取最大值提取

    ArcGIS案例学习笔记2_1_山顶点提取最大值提取 计划时间:第二天上午 目的:最大值提取 教程:Pdf page=343 数据:chap8/ex5/dem.tif 背景知识:等高线种类 基本等高线 ...

  5. ArcGIS案例学习笔记4_2

    ArcGIS案例学习笔记4_2 联系方式:谢老师,135_4855_4328,xiexiaokui#qq.com 时间:第4天下午 案例1:批量水文分析地理建模 数据:实验数据\Chp11\tutor ...

  6. ArcGIS案例学习笔记1_1

    ArcGIS案例学习笔记1_1 联系方式:谢老师,135_4855_4328, xiexiaokui#qq.com 时间:第一天上午 准备 0.U盘复制ArcGIS培训*** 1.练习数据不要放到桌面 ...

  7. ArcGIS案例学习笔记2_1

    ArcGIS案例学习笔记2_1 联系方式:谢老师,135_4855_4328,xiexiaokui#qq.com 时间:第二天上午 案例1:学校选址 内容:栅格数据分析 教程:pdf page=323 ...

  8. js学习笔记:webpack基础入门(一)

    之前听说过webpack,今天想正式的接触一下,先跟着webpack的官方用户指南走: 在这里有: 如何安装webpack 如何使用webpack 如何使用loader 如何使用webpack的开发者 ...

  9. Vue.js学习笔记(2)vue-router

    vue中vue-router的使用:

随机推荐

  1. Sql Server系列:触发器

    触发器的一些常见用途: ◊ 强制参照完整性 ◊ 常见审计跟踪(Audit Trails):这意味着写出的记录不仅跟踪大多数当前的数据,还包括对每个记录进行实际修改的历史数据. ◊ 创建与CHECK约束 ...

  2. Javascript算法系列之快速排序(Quicksort)

    原文出自: http://www.nczonline.net/blog/2012/11/27/computer-science-in-javascript-quicksort/ https://gis ...

  3. C#单例模式详解

    C#要实现单例模式必须要有以下三点: 声明私有静态成员.私有化构造函数.静态函数返回实例. private static GameManager s_GameManager=null; private ...

  4. Util应用程序框架公共操作类(九):Lambda表达式扩展

    上一篇对Lambda表达式公共操作类进行了一些增强,本篇使用扩展方法对Lambda表达式进行扩展. 修改Util项目的Extensions.Expression.cs文件,代码如下. using Sy ...

  5. EntityFramework 7 Join Count LongCount 奇怪问题(已修复)

    问题说明: 博客问题纪录 Use EF7, Linq Join Count is error EF7 Code Commit EF7 版本(注意 rc): 旧版本:"EntityFramew ...

  6. c# 我所理解的 值类型 and 引用类型

    一直以来对于值类型和引用类型都只是一个模糊的概念,趁最近有空深入理解了下. 先说说值类型,在msdn上是这样介绍值类型的. 意思就是值类型直接包含值. 变量引用的位置就是值所在内存中实际存储的位置,所 ...

  7. 记录一则ORA-12154,ORA-12560解决过程

    应用服务器:Windows Server 2008 R2 Enterprise 故障现象:项目侧同事反映应用服务器上的程序连接数据库报错:ORA-12560: TNS: 协议适配器错误 1.故障重现 ...

  8. 四大组件之ContentProvider

    前言 ContentProvider作为Android的四大组件之一,是属于需要掌握的基础知识,可能在我们的应用中,对于Activity和Service这两个组件用的很常见,了解的也很多,但是对Con ...

  9. ajax调用本地wcf中的post和get

    我们可以通过jQuery调用本地或者远程的wcf服务,本文讲解的是对本地wcf服务的post和get调用方式. post和get到底有什么区别呢?此处不作详述. 但是,post对请求的数据格式更为严格 ...

  10. 让我们一起用开源数据库和开源框架废弃Access

    一.为什么要废弃Access? 1.客户的机子上需要安装access的驱动 ps:这个比较烦人,大家都知道部署越简单越好,安装这个对用户来说太繁琐了. 2.操作时性能不佳 using System; ...