ArcGIS JS 学习笔记4 实现地图联动

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

时间: 2024-08-26 00:15:05

ArcGIS JS 学习笔记4 实现地图联动的相关文章

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

一.开篇 在博客注册了三年,今天才决定写第一篇博客,警告自己不要懒!!! 二.关于ArcGIS JS 版本选择 在写这篇博客时ArcGIS JS 4.0正式版已经发布.它和3.x版本的不同是,Map不在是一个控件,而真的只是一张“图”,Map(4.0版本)需要在一个View里面来展示,在MapView里面就是一张平面图,在SceneView里面就一张三维地图.同一张地图在不同的View里面就可以呈现出不同的效果.但是4.0版本才是一个最初的版本,还有很多3.x有的功能没有被加入到其中.所以我打算

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

1. 开篇 模仿是最好的学习,这次我们继续山寨百度,通过自定义Infowindow来实现百度风格的BubblePopup 2.准备 2.1 Copy模板 先打开百度地图,按下f12吧BubblePopup的HTML代码和CSS代码拷贝下来,这里我无耻的把类名改了,大家不要在意细节. HTML模板 1 <div class="dextra-bubble-pop-center" style="z-index: 3; position: relative; height: 5

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

一.前言 吐槽一下,百度在国内除了百度地图是良心产品外,其他的真的不敢恭维.在上一篇笔记里,我已经实现了自定义的地图测量模块.在百度地图里面(其他地图)都有一个周边搜索的功能,拖拽画一个圆,然后以圆半径进行搜索(也就是缓冲区╮(╯_╰)╭). 这次的目标,就是要山寨这个拖拽画圆的功能,我先放一个效果图. 二.开始山寨 我们先想一想要实现这个功能需要哪些步骤. 拖拽 画圆 通知拖拽结束 2.1 实现拖拽 关于拖拽,有graphicslayer的拖拽事件和map的拖拽事件,如何选择呢?先来看一看官方

Vue.js学习笔记(7)组件详解

在这篇文章之前小颖分享过小颖自己写的组件:Vue.js学习笔记(5)tabs组件和Tree升级版(实现省市多级联动) 先给大家看下小颖写了一个简单的组件示例: 组件: <template> <div class='content' v-if='showFlag'> <input type="text" v-bind:style='{ width:compwidth+"px"}' v-model='compvalue' @keyup='m

Vue.js学习笔记:在元素 和 template 中使用 v-if 指令

f 指令 语法比较简单,直接上代码: <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd"> <html> <head> <title></title> <script src="https://cdn.bootcss.com/vue/2.2.

[Pro Angular.JS]学习笔记1.1:设置开发环境

可以使用yeoman.io,很方便.我已经写了一篇随笔,介绍如何使用.这里也有一篇介绍的文章:http://www.cnblogs.com/JoannaQ/p/3756281.html 代码编辑器,在Mac下用了一下WebStorm,太恶心了.另外发现书的作者使用的开发环境是Windows + VS Express 2013,为了方便学习,我也使用VS Express 2013 Update2.VS2013用起来蛮舒服的,把WebStorm比得跟驼屎一样.也许是因为我没用习惯吧. 1.安装Nod

【转】Backbone.js学习笔记(二)细说MVC

文章转自: http://segmentfault.com/a/1190000002666658 对于初学backbone.js的同学可以先参考我这篇文章:Backbone.js学习笔记(一) Backbone源码结构 1: (function() { 2: Backbone.Events // 自定义事件 3: Backbone.Model // 模型构造函数和原型扩展 4: Backbone.Collection // 集合构造函数和原型扩展 5: Backbone.Router // 路由

Angular JS 学习笔记

特定领域语言 编译器:遍历DOM来查找和它相关的属性, 分为编译和链接两个阶段, 指令:当关联的HTML结构进入编译阶段时应该执行的操作,可以写在名称里,属性里,css类名里:本质上是函数 稳定的DOM:绑定了数据模型的DOM元素的实例不会在绑定的生命周期发生改变 作用域:用来检测模型的改变和为表达式提供执行上下文的 AngularJS 和其它模板系统不同,它使用的是DOM而不是字符串 指令: 由某个属性.元素名称.css类名出现而导致的行为,或者说是DOM的变化 Filter过滤器:扮演着数据

Node.js学习笔记(3) - 简单的curd

这个算是不算完结的完结吧,前段时间也是看了好久的Node相关的东西,总想着去整理一下,可是当时也没有时间: 现在看来在整理的话,就有些混乱,自己也懒了,就没在整理,只是简单的记录一下 一.demo的简单介绍 这次demo,只涉及到简单的curd操作,用到的数据库是mongo,所以要安装mongo数据库,数据库连接驱动是mongoose: 当然关于mongo的驱动有很多,比如mongous mongoskin等:(详见http://cnodejs.org/topic/4f4ca8e0940ce2e