Mapbox GL NavigationControl 事件

Mapbox GL NavigationControl Events

我有一个 Mapbox GL 地图实例,在加载我的数据源后,我调用 fitBounds() 来更改地图的中心并缩放以适合我的数据集。我还在这张地图上附加了一些事件监听器,因为我想知道用户何时手动更改了地图的缩放或位置。

Mapbox 还在 fitBounds() 上触发 'movestart' 和 'zoomstart',尽管我通过检查是否存在 originalEvent 属性 在事件回调中。

问题是,我还向地图添加了一个 NavigationControl,并且通过其缩放或旋转按钮触发的用户交互会在没有 originalEvent 属性 的情况下触发我的地图事件。我在 Mapbox 文档中找不到任何方法来监听 NavigationControl 的附加事件监听器,也找不到区分由 fitBounds 调用发起的缩放/平移与通过该组件进行的用户交互的方法。

有什么我想念的吗?有没有办法将鼠标/触摸事件监听器附加到 NavigationControl 组件?或者事件对象中是否有一些 属性 可以告诉我事件的来源?

简化的代码示例 -

this._userMoved = false;
this._map = new mapboxgl.Map(options);

// listen for user actions that update the map display
['movestart', 'zoomstart', 'boxzoomstart', 'rotatestart', 'pitchstart'].forEach((action) => {
  this._map.on(action, (e) => {
    if (e.originalEvent) {
      // if this property is set, the event in question was triggered by an actual user ineraction.
      // EXCEPT when the user interaction came from the NavigationControl, hence the problem
      this._userMoved = true;
    }
  });
});
this._map.on('load', () => {
  // add the control after map load
  this._map.addControl(new mapboxgl.NavigationControl(),'top-left');
  this._setMapData(); // adds my data source to the map
  this._setMapView(); // calls this._map.fitBounds() using my data source
});

如果您的需要是专门处理被调用一次的特定事件 (fitbounds),那么您可以这样做:

this._map.once('moveend', e => {
   // do whatever you do after the fitbounds event.
   this._map.on(['movestart', 'zoomstart', 'boxzoomstart', 'rotatestart', 'pitchstart'], userMovementHandler)
});

编辑

我只是更仔细地查看了文档,fitBounds 确实有一个 eventData 参数,旨在解决这个问题。

<!DOCTYPE html>
<html>
<head>
    <meta charset='utf-8' />
    <title>Display a map</title>
    <meta name='viewport' content='initial-scale=1,maximum-scale=1,user-scalable=no' />
    <script src='https://api.tiles.mapbox.com/mapbox-gl-js/v0.43.0/mapbox-gl.js'></script>
    <link href='https://api.tiles.mapbox.com/mapbox-gl-js/v0.43.0/mapbox-gl.css' rel='stylesheet' />
    <style>
        body { margin:0; padding:0; }
        #map { position:absolute; top:0; bottom:0; width:100%; }
    </style>
</head>
<body>

<div id='map'></div>
<script>
mapboxgl.accessToken = 'pk.eyJ1Ijoic3RldmFnZSIsImEiOiJGcW03aExzIn0.QUkUmTGIO3gGt83HiRIjQw';
var map = new mapboxgl.Map({
    container: 'map', // container id
    style: 'mapbox://styles/mapbox/streets-v9', // stylesheet location
    center: [-74.50, 40], // starting position [lng, lat]
    zoom: 9 // starting zoom
}).on('moveend', e => { 
    if (e.source === 'fitBounds') {
        console.log('Caused by fitBounds');
    } else {
        console.log('Caused by user');
    }
})
map.fitBounds([140,-42, 150,-37], {}, {source: 'fitBounds'})
</script>

</body>
</html>