我是靠谱客的博主 精明时光,最近开发中收集的这篇文章主要介绍leaflet中的事件穿透,觉得挺不错的,现在分享给大家,希望可以做个参考。

概述

在总结方法之前,先总结一下问题。

用过leaflet的人都知道,leaflet中有这样一个方法:

L.geoJSON(data, {
style: function (feature) {
return {color: feature.properties.color};
}
}).bindPopup(function (layer) {
return layer.feature.properties.description;
}).addTo(map);

这个方法可以将封装好的GeoJson直接转化为FeatureGroup,非常方便。

GeoJson 的 featureType 有多种,这里拿 Point 和 Polygon 两类来举例说明,它们在 leaflet 中是两个代表。Point 类型的 geojson 数据在转化为地图图层的渲染方式是 marker,本质上是 div,也就是说,如果你的 geojson 里有 1 万条数据,那它就会在地图上创建 1 万个 div,很恐怖有木有,事实上也是不可取,因为一口气创建一万个 div 还是带来了很大的工作量,一般配置的电脑上运行这样的页面会卡出翔;再说 Polygon 多边形类型,Polygon  类型的 geojson 数据在转化为地图图层的渲染方式是 Canvas,这与 marker 有本质上的区别,即使你的 geojson 里有 1 万条数据,它也只会在其所在的 Pane 上创建 1 个 Canvas标签,页面地图流畅程度丝毫不受影响。 

说到这里,其实离本文的问题已经跑远了,但说这些也是为了更好的理解这个问题或者说现象。div 是有层级关系(zIndex)的,而且这种关系是非常容易被控制的,任何时候我们都可以很轻易去改变,那么 Canvas 呢?

在 leaflet 的使用中可能会碰到这样的情况,在同一层的 Pane 上,比如在 “ overlayPane ” 上,同时定义了以三角形为主和以四边形为主的 Polygon 类型的 FeatureGroup,因此最后渲染出的页面应该是这两个 Feature Group 的内容展示在同一个 Canvas 标签中,假如它们分别都绑定了各自的popup事件,而恰好它们在地图上的区域有所交叉和重叠(假设三角形在四边形的上方,即三角形覆盖了四边形的重叠区域),那这下子就尴尬了,当点击地图上它们的重叠区域时,这个问题的高潮也就来了。

从理论上无非四种结果:触发三角形的popup;触发四边形的popup;二者都没触发;二者都触发了。

而从测试后的事实的表象来看,无论是哪儿的重叠区域,被触发的,永远是下方被覆盖的四边形。

一开始我是懵比的,我觉得这是一个诡异的bug,一个问题的发生找不到合乎逻辑的解释。寥寥数行代码我反复看的心疲力乏,有一句话最能描述我当时的心境,理智让我怀疑一切!

好了,不兜圈子了,这个bug神秘的面纱下,其实就是事件穿透,事实的本质是最后一种预想,二者都触发了。leaflet 中 popup 有个特性,整个地图中有且只能有一个 popup 会被触发,事情的真相是,当鼠标点击它们的重叠区域时,首先会触发位于上方的三角形,紧接着触发下方的四边形。触发四边形的过程中会解除掉三角形的触发状态。这就是真相,一个典型的事件穿透问题。

搞清楚了问题的来龙去脉,解决问题的思路就一下打开了,可能稍微棘手点的就是,popup事件都是绑定在同一个canvas中的每一个单元上。

直接上代码,后面不想再多说了,还是要留下一些思考的空间。

var level_active = false;
var ship_active = false;

 

/*=============================================== (实时)通航等级 ====================================================*/
function getPassLevelLayer() {
if (grade_cache == "") {
return;
}
levelLayer = L.geoJson(grade_cache, {
style: function (feature) {
return {color: feature.properties.color, weight: weightValueArray[map.getZoom()], pane: 'overlayPane'};
},
onEachFeature: function (feature, layer) {
layer.bindPopup(eachFeaturePopup(feature));
layer.on("mouseover",function(){
level_active = true;
}).on("mouseout",function () {
level_active = false;
}).on('click',function () {
if(level_active&&ship_active){
ship_popup_obj.openPopup();
}
});
}
});
return levelLayer;
}

 

/*===================================================== 船 舶 ========================================================*/
function loadShipSoapLayer() {
if (shipSoapLayer == null) {
shipSoapLayer = L.geoJson(ship_soap_cache, {
style: function (feature) {
return {
fillColor: feature.properties.Color,
fillOpacity: 1,
color: "black",
weight: 1,
pane: 'overlayPane'
}; 

},
onEachFeature: function (feature, layer) {
layer.bindPopup(eachShipFeaturePopup(feature), {
closeButton: false,
className: "ShipSoap",
Ship_Id: feature.properties.ShipId
}).on('popupopen ', function (e) {
if(level_active&&ship_active){
ship_popup_obj = e.target;
}
var shipid = map._popup.options.Ship_Id;
$('.ShipSoap-Foot_Btn').on('click', function () {
window.layer.open({
type: 2,
skin: 'layui-layer-hei',
title: '通航查询',
shadeClose: false,
shade: [0.9, '#6b6b6b'],
maxmin: false,
area: ['100%', '100%'],
content: 'ship.html&shipId=' + shipid
});
})
}).on('popupclose', function () {
$('.ShipSoap-Foot_Btn').unbind();
}).on("mouseover",function(){
ship_active = true;
}).on("mouseout",function () {
ship_active = false;
});
}
}).setZIndex('9999');
}
return shipSoapLayer;
}

 

转载于:https://www.cnblogs.com/unique1319/p/7813858.html

最后

以上就是精明时光为你收集整理的leaflet中的事件穿透的全部内容,希望文章能够帮你解决leaflet中的事件穿透所遇到的程序开发问题。

如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。

本图文内容来源于网友提供,作为学习参考使用,或来自网络收集整理,版权属于原作者所有。
点赞(62)

评论列表共有 0 条评论

立即
投稿
返回
顶部