zoukankan      html  css  js  c++  java
  • ArcGIS API for js 地图联动

    1.开篇

          这次我的模仿目标是天地图的地图联动。

    image

    天地的地图联动不仅地图有联动,而且鼠标也有联动,我就照着这个目标进行山寨。

    2.准备

          地图联动其实就是当一张的extent发生了变化,另一张图的extent也要同步变化,这样就可以两张图的范围同步了。同理,这样就可以扩展到N张图进行联动。所以这次的目标就是实现添加任意的地图都要可以联动。首先依然是先看一下官方文档。找到有用的方法或者事件。

    image

    image

    image

    image

    image

         整体的难点在于如何判断主地图(有鼠标动作的地图),通过官方文档,我们可以利用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="49%;float:left"></div>
    106 <div id="map2" style="49%; float:right"></div>
    107 <div id="map3" style="49%; "></div>
    108 </body>
    109 </html>
    复制代码

    有图有真相:

    imageimage

  • 相关阅读:
    关于C语言中%p和%X的思考
    multimap员工分组案例
    set容器查找操作使用
    绘制漂亮的思维导图
    [deque容器练习]打分案例
    【LeetCode】1162. 地图分析
    【LeetCode】820. 单词的压缩编码
    【LeetCode】914. 卡牌分组
    【LeetCode】999. 车的可用捕获量
    【LeetCode】3. 无重复字符的最长子串
  • 原文地址:https://www.cnblogs.com/tuboshu/p/10752413.html
Copyright © 2011-2022 走看看