map-view
本文回答:视图变更事件 —— move / moveend / zoom / rotate / pitch 以及何时用 start/end。
一、事件对
| 起 / 进行 / 止 |
|---|
movestart / move / moveend |
zoomstart / zoom / zoomend |
rotatestart / rotate / rotateend |
pitchstart / pitch / pitchend |
dragstart / drag / dragend |
二、move 组合
map.on('move', () => console.log(map.getCenter())); // 每帧 fire
map.on('moveend', () => save(map.getCenter())); // 停稳后 fire 一次
move高频,用于实时联动(比如指北针跟随旋转)moveend低频,适合持久化 / 请求
三、zoom
map.on('zoom', () => hud.zoom = map.getZoom().toFixed(1));
map.on('zoomend', () => fetchTilesForZoom(map.getZoom()));
四、rotate / pitch
map.on('rotate', () => {
compass.style.transform = `rotate(${-map.getBearing()}deg)`;
});
map.on('pitchend', () => {
if (map.getPitch() === 0) reset2D();
});
五、drag(平移拖拽)
map.on('dragstart', () => isDragging = true);
map.on('dragend', () => isDragging = false);
六、高频事件 + RAF
let pending = false;
map.on('move', () => {
if (pending) return;
pending = true;
requestAnimationFrame(() => {
update();
pending = false;
});
});
或直接用 moveend:
map.on('moveend', () => update());
七、地图边界监听
map.on('moveend', () => {
const bounds = map.getBounds();
loadDataInBounds(bounds);
});
// CAD 坐标(当前视野)
map.on('moveend', () => {
// ⚠️ 不要用 map.getGeoBounds()——它返回"全图范围×ratio"(不随视野变化)。
// 当前视野的 CAD 范围:把 LngLatBounds 反算
const cadBounds = map.fromLngLat(map.getBounds()); // 传 LngLatBounds 直接返回 GeoBounds
// 旋转 / 倾斜时可逐角点:map.fromLngLat(map.unproject([0,0])) / unproject([w,h])
});
八、程序化移动也 fire 事件
flyTo / easeTo / jumpTo / fitBounds 都会触发 move 事件。避免循环:
let suppress = false;
map.on('move', () => {
if (suppress) return;
// 处理用户拖动
});
suppress = true;
map.flyTo({ center: [116, 39] });
map.once('moveend', () => suppress = false);
九、视图参数速查
| 方法 | 返回 |
|---|---|
getCenter() |
{ lng, lat } |
getZoom() |
number |
getBearing() |
度(0 = 正北) |
getPitch() |
度(0 = 水平) |
getBounds() |
LngLatBounds |
getGeoBounds(ratio?) |
全图范围 × ratio 的 CAD GeoBounds,不随视野变化;当前视野用 map.fromLngLat(map.getBounds()) |
十、同步多图视图
见 overlay/sync-view。核心:
map1.on('move', () => {
if (syncing) return;
syncing = true;
map2.jumpTo({
center: map1.getCenter(),
zoom: map1.getZoom(),
bearing: map1.getBearing(),
pitch: map1.getPitch()
});
syncing = false;
});
十一、常见坑
- 在
move里flyTo:无限递归。 moveend后立即 setData:仍然是同一帧,可能卡;考虑放到idle后。- bearing = 0 不等于无旋转:接近 0 可能 0.0001;用
Math.abs(map.getBearing()) < 0.1判断"近乎正北"。 - pitch > 0 下 mousemove 坐标偏差:远处的像素映射到 CAD 坐标范围很大;用业务的距离阈值。
- moveend 不 fire:如果编辑 canvas 位置 / 尺寸没调用
map.resize(),内部状态未变 → 可能不触发;手动map.resize()。
相关
- 交互 → map-interaction
- 性能 → perf/event-throttling
- 视图同步 → overlay/sync-view