前言

ArcGIS API如同国内用的不多,除了设计院以外,大多数还是用的百度和高德API。
ArcGIS API的文档是全英文,因而分享一些小性能的实现思路。

需要

ArcGIS中,新增加的图层永远在最下面,就像这样:

而在业务逻辑上,有时咱们须要某个图层置顶。
比方用来统计面积大小的图层,如果它被其余图层笼罩掉,就不能失常的统计面积和显示被选中的地块了:

本文就来解决这个问题

先说原理,非常简单,应用到生命周期钩子函数。

尝试的其余办法

首先尝试了add图层是能不能手动设置order,也就是给它设置的地位很高,比方100:

为了便于交换,咱们临时把这个图层叫做areaSumLayer

// 业务上须要置顶的图层let areaSumLayer: GraphicsLayer// 增加图层时设置的很高map.add(areaSumLayer,100);

事实上这样不行,因为后面提到它的逻辑是:“新增加的图层永远在最下面”
即便以前的图层设置的很高,新图层还会更高,比方地位在101。

因而咱们的思路是:
无奈在创立areaSumLayer时保障它当前是置顶的
而是在创立其余图层时保护一下areaSumLayer的地位

生命周期钩子

什么是生命周期?所有的前端组件都应用了这个思维。生命周期指的是从一个组件从创立到沦亡的过程。

拿前端框架Angular举例,最常见的包含:

  • ngOnInit(): 组件创立
  • ngOnChanges(): 绑定的数据发生变化时
  • ngOnDestoryed(): 组件销毁

https://angular.cn/guide/lifecycle-hooks

或者VUE中:

  • created(): 组件创立
  • mounted(): 组件渲染结束
  • beforeUpdate():产生变更前
  • updated(): 产生变更
  • unmounted(): 组件登记
https://cn.vuejs.org/guide/essentials/lifecycle.html

这些生命周期钩子是在框架开发者编写时就写好的,要应用这些周期函数,只须要用回调的形式,传入一个咱们本人写好的办法,这个办法会在适当的机会(生命周期产生时)被主动调用,用到的就是订阅者-观察者模式。

ArcGIS API

接下来看看ArcGIS的图层有什么生命周期(官网称之为事件event):

https://developers.arcgis.com/javascript/latest/api-reference...
  • before-add:增加前
  • after-add:增加后
  • before-changes:变更前
  • change:变更
  • after-changes:变更后
  • before-remove:销毁前
  • after-remove:销毁后

有这么多生命周期,而咱们的业务上用到的是增加后,也就是“当新图层增加后,咱们手动的更新一下须要置顶的areaSumLayer图层。

after-add是这样用的:

https://developers.arcgis.com/javascript/latest/api-reference...
map.layers.on("after-add", function(event){  console.log(event.item.id);});
  • map.layers.on是开启监听,map就是Map类创立的对象
  • "after-add"是监听的事件类型,咱们须要监听增加图层之后的事件
  • event是本人写的回调函数中的变量
  • 办法体是咱们要在回调时执行的操作

失常状况下,当有新的图层被增加进来时,控制台就会输入它的ID。

接下来是寻找:areaSumLayer有没有曾经被增加
须要用到collection汇合的find办法:

https://developers.arcgis.com/javascript/latest/api-reference...

find办法是寻找某个图层在不在图层汇合中,应用的还是回调函数:

        // 如果此时图层汇合中有面积的图层        if (map.layers.find(function (layer) {            return layer.id === areaSumLayer.id        })){            console.log("true");        }

逐条解释:

咱们定义了一个办法:

function (layer) {    return layer.id === areaSumLayer.id}
  • layer是回调时的变量,能够轻易写,但要和办法体中对应
  • 办法的内容就是:判断回调变量的图层id和咱们的id是否相等,如果相等,阐明咱们要查问的图层在这个汇合中,返回true

接下来解决“调整图层程序”的步骤:

// 从新增加面积图层map.remove(areaSumLayer);map.add(areaSumLayer);
  • 就是先暗藏再从新增加

因而合起来就变成了这样:

    /**     * 地图生命周期     * 当图层创立后,把预览图片的图层从新增加一下,使其永远置顶     */    map.layers.on('after-add', (event) => {        // 如果此时图层汇合中有areaSumLayer图层        if (map.layers.find(function (layer) {            return layer.id === areaSumLayer.id        })) {            // 从新增加areaSumLayer图层            map.remove(areaSumLayer);            map.add(areaSumLayer);        }    })

此时,只有有别的图层增加结束,钩子函数就会从新把areaSumLayer置顶。

但当初有个问题:如果新增加的图层就是areaSumLayer呢?还会触发这个钩子函数吗?
答案是:会产生死循环。

解决这个问题很简略,先从event中把刚刚增加的图层id获取到:

// 刚刚增加的图层id,为了避免死循环let justAddedId = event.item.id;

此时,如果justAddedId等于areaSumLayer的id,就阐明方才增加的就是areaSumLayer图层,就不必再执行调整操作了。

最终的代码:

    /**     * 地图生命周期     * 当图层创立后,把预览图片的图层从新增加一下,使其永远置顶     */    map.layers.on('after-add', (event) => {        // 获取刚刚增加的图层id,为了避免死循环        let justAddedId = event.item.id;        // 如果此时图层汇合中有areaSumLayer图层        if (map.layers.find(function (layer) {            return layer.id === areaSumLayer.id        // 并且刚增加的图层不是areaSumLayer图层        }) && (justAddedId != areaSumLayer.id)) {            // 从新增加areaSumLayer图层            map.remove(areaSumLayer);            map.add(areaSumLayer);        }    })

总结

当我刚接手这个性能的时候,我甚至没有残缺的看一遍ArcGIS的文档(又是英文,又特地长,文档内容比Angular都多)。
但所有框架的思维都是相通的,编程编的就是思维,依据其余框架的教训就能够推断ArcGIS肯定有相似的办法,再去文档中查问即可。