共计 2938 个字符,预计需要花费 8 分钟才能阅读完成。
前言
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 肯定有相似的办法,再去文档中查问即可。