返回笔记列表
01 · NOTES / WebGIS 开发

第 06 节 · 事件与交互

2026 年 9 月 1 日

第 06 节 · 事件与交互

📌 版本信息:Leaflet 1.9.4(2026-08-29 核对) 📚 来源:Leaflet 事件参考(map / layer 两张事件表) 🎯 Leaflet 的事件体系与 DOM 事件同源(第 15 节模块 02 的知识直接平移),但对象是"地图世界"的。

一、这一节的目标

  1. 掌握 map 层高频事件:click / moveend / zoomend / movestart
  2. 掌握图层事件:marker click / layer mouseover
  3. 掌握事件对象 e 的地图信息:latlng / layerPoint / target
  4. 完成交互 playground(一切交互功能的试验田)

二、两类事件对象

// map 事件:e 是"地图事件"——带地理位置
map.on('click', (e) => {
  e.latlng;            // ← LatLng:点在哪(最常用!)
  e.layerPoint;        // 相对地图原点的像素
  e.containerPoint;    // 相对容器的像素
});

// 图层事件:e 是"图层事件"——带 target
marker.on('click', (e) => {
  e.target;            // ← 触发的 marker 本身(拿它的 latlng/getPopup())
});
// ⚠️ Leaflet 事件不冒泡到 map(与 DOM 不同):marker 的 click 不会触发 map 的 click
//    (省去了"事件委托"的思考——各管各的)

// 高频 map 事件:
map.on('moveend', ...)   // 拖动/飞行结束(联动查询"当前视野内的数据"的时机!)
map.on('zoomend', ...)   // 缩放结束(联动分级渲染)
map.on('movestart', ...) // 开始移动(隐藏弹窗/暂停刷新)
map.on('resize', ...)    // 容器尺寸变化(invalidateSize 场景)

💡 WebGIS 黄金组合moveend + getBounds() + 请求视野内数据——"地图挪到哪,数据查到哪"(替代一次性拉全量数据)。模块 13 的后端 bbox 接口就是为它准备的。


三、交互 playground 的标准内容

// ① 点击地图打点(第 03 节埋的 TODO 正式实现)
map.on('click', (e) => {
  L.marker(e.latlng).addTo(map).bindPopup(e.latlng.toString());
});

// ② 双击冲突问题:dblclick 会先触发两次 click!
//    解法:需要双击语义时用 setTimeout 延迟单击判断(250ms 内有第二击则取消单击逻辑)
let clickTimer;
map.on('click', (e) => {
  clearTimeout(clickTimer);
  clickTimer = setTimeout(() => singleClickLogic(e), 250);
});
map.on('dblclick', () => clearTimeout(clickTimer));

// ③ 悬停高亮 + 拾取(矢量要素):第 05 节已实践(onEachFeature 里 layer.on('mouseover'))

// ④ 键盘/控件事件与地图联动:如输入经纬度后 flyTo(第 01 节做过)

四、动手跟练:06 · 交互 playground

配套文件:05-leaflet/examples/06-交互playground.html

步骤:

  1. 一个"实验场"页面:所有事件触发都在右侧日志面板滚动打印(map.on('click/moveend/zoomend/movestart/zoomstart/mousemove') 全注册,节流 mousemove)
  2. 完成 6 个 TODO:点击打点(含双击冲突消解)、moveend 时打印当前 bounds 与中心、"视野内数据"模拟(过滤本地数据集打点)、escape 键关闭所有弹窗(map.closePopup())、拖动 marker 事件、节流版 mousemove 显示实时经纬度(右侧状态条)
  3. 观察事件触发顺序:点击一次会产生 click(+ dblclick 与否)、moveend 何时来——把顺序写进注释

通关标准:

  • 事件日志面板正常滚动
  • 双击/单击冲突消解实现
  • "视野内数据"模式能讲清(moveend + getBounds + 过滤/请求)

五、自测题

  1. Leaflet 的事件会冒泡吗?与 DOM 的差异?
  2. moveend + getBounds + 请求数据的黄金组合是什么?
  3. 双击触发几次 click?如何消解?
  4. e.latlng 与 e.target 各属于哪类事件对象?
  5. marker 的 click 会触发 map 的 click 吗?

参考答案

  1. 不冒泡(map 与图层事件独立);DOM 会冒泡——所以 DOM 的委托模式在这里不需要。
  2. 拖/缩结束 → 取 getBounds() → 用 bbox 向后端查该范围数据 → 渲染。数据按视野动态加载。
  3. 两次 click + 一次 dblclick;setTimeout 延迟单击 + dblclick 时 clearTimeout。
  4. e.latlng 是 map 事件对象(地理坐标);e.target 是图层事件对象(触发的图层引用)。
  5. 不触发——marker 自己的 click 处理了,地图收不到。

六、下一步

交互通了 → 第 07 节:图层组织与控件——多图层管理的秩序感。