唯杰地图 logo唯杰地图
VJMAP
EN

map-view

vjmap/references/event/map-view.md 3.7 KB143 行
原文

本文回答:视图变更事件 —— 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;
});

十一、常见坑

  1. 在 move 里 flyTo:无限递归。
  2. moveend 后立即 setData:仍然是同一帧,可能卡;考虑放到 idle 后。
  3. bearing = 0 不等于无旋转:接近 0 可能 0.0001;用 Math.abs(map.getBearing()) < 0.1 判断"近乎正北"。
  4. pitch > 0 下 mousemove 坐标偏差:远处的像素映射到 CAD 坐标范围很大;用业务的距离阈值。
  5. moveend 不 fire:如果编辑 canvas 位置 / 尺寸没调用 map.resize(),内部状态未变 → 可能不触发;手动 map.resize()。

相关