Javascript 在mapbox gl js中的图层上注册单击事件时如何处理事件冒泡

Javascript 在mapbox gl js中的图层上注册单击事件时如何处理事件冒泡,javascript,events,mapbox-gl-js,Javascript,Events,Mapbox Gl Js,如何停止层单击事件上的事件传播 mapBox.on('click',layerId,函数(e){ 控制台日志(e); //e.停止播放();这不起作用 //e.originalEvent.stopPropagation();它不工作 var popupHtml=getPopupHtmlWrapper(e.features[0]); 新建mapboxgl.Popup({closeButton:false}) .setLngLat(e.lngLat) .setHTML(popupHtml) .add

如何停止层单击事件上的事件传播

mapBox.on('click',layerId,函数(e){
控制台日志(e);
//e.停止播放();这不起作用
//e.originalEvent.stopPropagation();它不工作
var popupHtml=getPopupHtmlWrapper(e.features[0]);
新建mapboxgl.Popup({closeButton:false})
.setLngLat(e.lngLat)
.setHTML(popupHtml)
.addTo(地图盒);
});

我不知道有什么简单的方法来处理这个问题。我假设您正在尝试阻止单击事件传播到其他层。您可以使用一个全局变量来存储刚刚在这些坐标处发生的单击。然后在另一个单击处理程序中检查此情况

var-recentClicks={layer1:null}
mapBox.on('click',“layer1”,函数(e){
控制台日志(e);
最近点击次数[“第1层”]=e.lngLat
//继续创建弹出窗口
});
mapBox.on('click',“layer2”,函数(e){
控制台日志(e);
如果(最近点击[“layer1”]&最近点击[“layer1”][0]==e.lngLat[0]&最近点击[“layer1”][1]==e.lngLat[1]){
最近点击次数[“layer1”]=null
返回
}否则{
//继续处理第2层单击事件
}

});也许我们不需要全局变量,我遇到了与您相同的问题,我用解决方案解决了它:

mapbox.on('click','layer1',函数(e){
e、 originalEvent.cancelBubble=true;
/*
//或者您可以添加属性
e['bubble']='no';
*/
console.log('layer1');
}
在('click','layer2',函数(e){
如果(如原始事件取消气泡){
返回;
}
/*
如果(e['bubble]&&e['bubble']=='no'){
返回;
}   
*/
console.log('layer2');

}
一种方法是保存点击图层的事件坐标,然后将这些坐标与底层及其事件坐标进行比较

let clickCoords = {};

this.map.on('click', 'points', event => {
  clickCoords = event.point;
  console.log('Layer click')
});

Now, detect a click on the map, not on the points layer

this.map.on('click', () => {
  // check if coords are different, if they are different, execute whatever you need
  if (clickCoords.x !== event.point.x && clickCoords.y !== event.point.y) {
    console.log('Basemap click');
    clickCoords = {};
  }
});
或者,更好的是,使用


下面是一个。

根据@Stophface的建议,我使用了

e => {
  const features = map.queryRenderedFeatures(e.point)
  if (features[0].layer.id === myLayerName ) {
    doMyClickAction(e)
  }
}

因此,当我在本例中关心的层是第一个被单击的层时,仅对事件执行某些操作。

Mapbox提供对原始事件的访问。这意味着,每当我们想将
单击限制为仅单击的最顶层时,我们所需要做的就是调用
e.originalEvent.preventDefault()
在第一层上,并在下面的层中检查
e.originalEvent.defaultPrevented

this.map
.on('click','layer_1',函数(e){//最顶层
e、 originalEvent.preventDefault();
//第1层功能
})
.on('click','layer_2',函数(e){///第二顶层
如果(!e.originalEvent.defaultPrevented){
//单击是在层_1之外执行的
e、 originalEvent.preventDefault();
//第2层专用功能
}
})
.on('click'、'layer_3',功能(e){
如果(!e.originalEvent.defaultPrevented){
//单击是在第1层和第2层之外执行的
e、 originalEvent.preventDefault();
//第3层的独家功能在此。。。
}
...
})

正在寻找相同的解决方案,但在映射和层之间共享事件,因此,例如,如果未单击层,我希望调用映射单击侦听器,反之,如果单击层,我希望跳过映射单击侦听器

因此,我最终得出以下结论:

//层的事件处理程序
职能(e){
e、 预防默认值()
//处理层事件
}
//映射的事件处理程序
职能(e){
如果(如defaultPrevented)返回
//处理映射事件
}

因此,“防止默认设置”起作用,但您应该在事件中检查
defaultPrevented
属性并处理它。

在我通过在添加层时设置
beforeLayer
参数来调整层顺序后,上面的一些建议起作用:


如果以上建议对您都不起作用,请尝试使用图层顺序并再次查看它们。

您试图阻止事件冒泡到什么位置?@mollymerp我已尝试将cancelBubble属性设置为true,也尝试了StopperPagation方法,但均未成功(在从回调中获得e.OriginaleEvent对象时)为什么当您使用
mapbox覆盖函数体中的
e
时,如果(e.originalEvent.cancelBubble){…
true
,那么
会出现这种情况呢
e => {
  const features = map.queryRenderedFeatures(e.point)
  if (features[0].layer.id === myLayerName ) {
    doMyClickAction(e)
  }
}