【问题标题】:Mapbox GL NavigationControl EventsMapbox GL NavigationControl 事件
【发布时间】:2018-01-11 17:22:38
【问题描述】:

我有一个 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
});

【问题讨论】:

    标签: mapbox-gl-js


    【解决方案1】:

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

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

    编辑

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

    <!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> 

    【讨论】:

    • 这是个好主意;但是(我在原始帖子中没有提到这一点)我的地图数据将随着时间的推移而不断变化,随着这些变化的出现,我将重新调整地图的边界,直到用户进行第一次交互。
    • 很好的发现!不知道我是如何在文档中错过的。还有一个问题是 map.resize() 触发了moveend 事件,并且无法在该调用中传递eventData,但这应该由 Mapbox 处理,我找到了一种解决方法。谢谢!
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-03-14
    • 1970-01-01
    • 2017-01-26
    • 2016-06-05
    相关资源
    最近更新 更多