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