01 · NOTES / WebGIS 开发
第 06 节 · 事件与交互
2026 年 9 月 1 日
第 06 节 · 事件与交互
📌 版本信息:Leaflet 1.9.4(2026-08-29 核对) 📚 来源:Leaflet 事件参考(map / layer 两张事件表) 🎯 Leaflet 的事件体系与 DOM 事件同源(第 15 节模块 02 的知识直接平移),但对象是"地图世界"的。
一、这一节的目标
- 掌握 map 层高频事件:click / moveend / zoomend / movestart
- 掌握图层事件:marker click / layer mouseover
- 掌握事件对象 e 的地图信息:latlng / layerPoint / target
- 完成交互 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
步骤:
- 一个"实验场"页面:所有事件触发都在右侧日志面板滚动打印(
map.on('click/moveend/zoomend/movestart/zoomstart/mousemove')全注册,节流 mousemove) - 完成 6 个 TODO:点击打点(含双击冲突消解)、moveend 时打印当前 bounds 与中心、"视野内数据"模拟(过滤本地数据集打点)、escape 键关闭所有弹窗(map.closePopup())、拖动 marker 事件、节流版 mousemove 显示实时经纬度(右侧状态条)
- 观察事件触发顺序:点击一次会产生 click(+ dblclick 与否)、moveend 何时来——把顺序写进注释
通关标准:
- 事件日志面板正常滚动
- 双击/单击冲突消解实现
- "视野内数据"模式能讲清(moveend + getBounds + 过滤/请求)
五、自测题
- Leaflet 的事件会冒泡吗?与 DOM 的差异?
- moveend + getBounds + 请求数据的黄金组合是什么?
- 双击触发几次 click?如何消解?
- e.latlng 与 e.target 各属于哪类事件对象?
- marker 的 click 会触发 map 的 click 吗?
参考答案
- 不冒泡(map 与图层事件独立);DOM 会冒泡——所以 DOM 的委托模式在这里不需要。
- 拖/缩结束 → 取 getBounds() → 用 bbox 向后端查该范围数据 → 渲染。数据按视野动态加载。
- 两次 click + 一次 dblclick;setTimeout 延迟单击 + dblclick 时 clearTimeout。
- e.latlng 是 map 事件对象(地理坐标);e.target 是图层事件对象(触发的图层引用)。
- 不触发——marker 自己的 click 处理了,地图收不到。
六、下一步
交互通了 → 第 07 节:图层组织与控件——多图层管理的秩序感。