解决mapbox中事件冲突的几种方法
最近在基于mapbox做项目,随着功能越来越多,mapbox上的事件冲突也越来越严重。比如说一个人需要实现在地图上点击一下出现一个弹窗显示当前地点的效果,另外一个人需要实现在地图上点击选中某片区域的功能,最终得到的效果是当用户在地图上点击以后既出现了弹窗又选中了某片区域。
例如下面的代码会导致点击地图后同时在控制台打印两条信息1
2
3
4
5
6
7
8map.on("load", () => {
map.on("click",() => {
console.log("click 1")
})
map.on("click",() => {
console.log("click 2")
})
});
从下图中可以看出click事件被响应了两次
下面是解决这些问题的一些思路,仅供参考。
- e.preventDefault
e.preventDefault()本身是用来阻止事件发生后的默认行为的。例如下面的代码可以屏蔽掉mapbox的拖拽移动等功能
1 | map.on("load", () => { |
但是默认情况下这个只会阻止mapbox上的一些默认行为,只在代码里加一个e.preventDefault并不能阻止我们自己代码里的一些冲突。所幸的是,在调用了e.preventDefault()之后,e.defaultPrevented会被修改为true,因此,我们的代码里可以通过判断这个值来避免事件的冲突。下面是示例代码:1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16map.on("load", () => {
map.on("click",e => {
if(e.defaultPrevented){
return;
}
e.preventDefault();
console.log("click 1")
})
map.on("click",e => {
if(e.defaultPrevented){
return;
}
e.preventDefault();
console.log("click 2")
})
});
从下图中可以看出click事件被响应了一次(实际上是两次,但是第二次直接返回了)
- 故意出错
这个方案不太好,就是故意加一些出错的代码,这样js在执行到出错的代码后就不再往下执行了。1
2
3
4
5
6
7
8
9
10map.on("load", () => {
map.on("click",e => {
console.log("click 1")
console.log(i)
})
map.on("click",e => {
console.log("click 2")
console.log(i)
})
});
从下图中可以看出click事件被响应了一次
但是相信这样的代码对于大多数人来说连编译都过不了
- 重写mapbox的on和off方法
前面的方法1虽然可以避免部分的事件冲突,但是一方面我们的遗留代码比较多,一处一处的修改不太现实,另一方面除了解决冲突外,我们可能也会希望有些监听能够优先被响应(类似于css中的z-index)。
熟悉面向对象的朋友都应该知道子类可以重写父类的方法。因此我们可以设计出一个子类来继承mapboxgl.Map,重写Map的on和off方法,同时也要考虑兼容以前的用法。
由于我的代码水平不高,下面的代码完全仅供参考
1 | class iMap extends mapboxgl.Map { |
使用的话,只需要把原来的new mapboxgl.Map() 换成 new iMap()
1 | mapboxgl.accessToken = |
下面是调用示例1
2
3
4
5
6
7
8
9
10
11
12
13
14
15map.on("load", () => {
map.on("click", (e) => {
console.log("虽然我排在第一个,但是由于我的优先级低(默认为0),而且前面的调用返回了false,所以我不会被调用");
});
map.on("click", (e) => {
console.log("虽然前面的调用返回了false,但是我的forceCall被设置为了true,所以仍然会被调用");
},1,true);
map.on("click", (e) => {
console.log("我的优先级排第二,我要阻止事件的继续向下传播");
return false;
},7);
map.on("click", (e) => {
console.log("虽然我排在最后,但是由于我的优先级最高,会被第一个调用");
},9);
});
下面是执行结果
完整代码请参考这个地址
同时基于iMap,我们也可以重写mapbox.marker,来避免两个marker在重叠时点击其中一个marker会导致两个marker都响应点击事件的情况
原文作者: 李小飞
原文链接: https://www.lixf.cc/2020/06/21/mapbox-event-conflict2/
版权声明: 转载请注明出处(必须保留作者署名及链接)