乐趣区

关于arcgis:使用ArcGIS-API生命周期钩子实现某个图层保持置顶

前言

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 肯定有相似的办法,再去文档中查问即可。

退出移动版