图层与图层组
Leaflet 里地图上没有「图形」这个概念,只有图层。瓦片、标记、线、面、弹窗都是图层。
单个图层各自 addTo(map) 也能显示,但成组管理才能一次显示、一次清空、
一次绑定事件。这一页把 LayerGroup、FeatureGroup 与 pane 的分工讲清楚。
四种容器,用途不同
| 类型 | 能做什么 | 典型场景 |
|---|---|---|
L.Layer | 单个图层,addTo / remove | 一个标记、一条线 |
L.LayerGroup | 批量增删、统一显隐 | 按业务分类的图层集合 |
L.FeatureGroup | 继承 LayerGroup,额外支持事件、getBounds() | 需要整体点击或视野适配 |
L.GeoJSON | 由 GeoJSON 生成,本身就是一个 FeatureGroup | 面数据、行政区 |
FeatureGroup 是 LayerGroup 的子类,多出来的能力都围绕「整体」:
整体绑定 click、整体算外包范围、整体 bringToFront()。
选哪个只看一件事:需不需要把这一组当成一个对象来对待。
LayerGroup:批量增删
图层组本身也是图层,所以它可以 addTo(map);之后往组里加东西,
会自动出现在地图上,不需要再调用一次 addTo。
var group = L.layerGroup().addTo(map);
group.addLayer(L.marker([39.907359, 116.391263]));
group.addLayer(L.circle([39.907359, 116.391263], {
radius: 400,
color: '#17694a',
fillOpacity: 0.2
}));
// 全部移除,组本身仍在地图上,可以继续加
group.clearLayers();
// 组一起下线
map.removeLayer(group);
group.addTo(map); // 再上线,之前清空的图层不会回来
clearLayers() 只清空内容,不摘掉组;map.removeLayer(group)
摘掉组,组内所有图层随之从地图上消失,但组对象和它的子图层依然存在,
重新 addTo 时加回来的是当前保留的内容。
FeatureGroup:整体事件与范围
一组标记要共用一个点击处理,逐个绑定既啰嗦又容易漏。
绑在组上,事件会从子图层冒泡上来,e.layer 就是被点中的那个。
var stations = L.featureGroup([
L.marker([39.907359, 116.391263]).bindTooltip('天安门'),
L.marker([39.916345, 116.397155]).bindTooltip('王府井'),
L.marker([39.899000, 116.407000]).bindTooltip('前门')
]).addTo(map);
stations.on('click', function (e) {
var layer = e.layer; // 被点中的子图层
var ll = layer.getLatLng();
console.log(ll.lat, ll.lng);
});
map.fitBounds(stations.getBounds(), { padding: [24, 24] });
事件冒泡方向是单向的。子图层的事件会传到组,组上绑定的事件不会反过来触发到子图层。
e.layer 在组级监听里才有值,在单个标记的监听里没有这个字段。
pane:控制叠放层次
同一张地图上,不同图层落在不同的 pane(面板)里,pane 决定谁压谁。 默认 pane 与层级如下,数值越大越靠上:
| pane 名称 | 默认 z-index | 放什么 |
|---|---|---|
tilePane | 200 | 瓦片底图 |
overlayPane | 400 | 默认矢量图层、GeoJSON |
shadowPane | 500 | 标记阴影 |
markerPane | 600 | 标记图标 |
tooltipPane | 650 | 提示框 |
popupPane | 700 | 弹窗 |
// 新建一个专门放注记的面板,压在标记之下
map.createPane('labels');
map.getPane('labels').style.zIndex = 550;
map.getPane('labels').style.pointerEvents = 'none';
L.marker([39.907359, 116.391263], { pane: 'labels' }).addTo(map);
pointerEvents: none 让这一层不接收鼠标,避免注记挡住下面的要素。
纯展示的文字层都应该这么设置。
注意事项
把 GeoJSON 当普通图层逐个加
L.geoJSON(data) 本身是 FeatureGroup,直接 addTo 即可。
再对每个 feature 建 L.polygon 逐个添加,等于放弃了 getBounds
与统一事件,也更容易在更新数据时漏删旧的图层。
用 clearLayers 之后没重置引用
清空后组对象仍可用,但如果代码里另存了某个子图层的引用,那个引用已经不在图上。
重新添加要再 addLayer 一次,否则点上去毫无反应。
指望 zIndex 跨 pane 生效
zIndex 只在同一个 pane 内的兄弟节点之间比较。
把两个图层的 z-index 调成 999 和 1,只要它们在不同 pane,结果仍由 pane 决定。
经纬志(2026)。《图层与图层组》。https://www.jingweizhi.com/leaflet/tutorial/layers-groups.html(访问日期 2026-11-03)。