01 · NOTES / WebGIS 开发
第 05 节 · GeoJSON 图层(数据上地图)
2026 年 9 月 1 日
第 05 节 · GeoJSON 图层(数据上地图)
📌 版本信息:Leaflet 1.9.4(2026-08-29 核对) 📚 来源:Leaflet GeoJSON 教程 | RFC 7946 | 数据:DataV GeoAtlas(全国/省界 GeoJSON,CORS 开放)、USGS GeoJSON Feed 🎯 本模块含金量最高的一节:前面是"往地图上摆东西",这节开始是"把数据变成地图"。
一、这一节的目标
- 精通
L.geoJSON()的三大回调:style / pointToLayer / onEachFeature - 掌握"数据驱动渲染"完整模式:fetch GeoJSON → 样式映射 → 交互绑定
- 理解 filter 过滤与 GeoJSON 图层的更新(setData)
- 完成"省界 + 实时地震"双数据渲染
二、L.geoJSON 三大回调(本节的全部精髓)
const layer = L.geoJSON(geojsonData, {
// ① style:Vector 图层(线/面)的样式——每个要素调用一次
// 函数参数是 feature → 可以按属性决定样式(专题图的根基!)
style(feature) {
return {
color: '#1677ff', // 线色/面边框
weight: 2, // 线宽
fillOpacity: 0.1, // 填充透明度
// 按属性映射:人口越多填充越深(分级统计图的雏形,第 13 节正式做成专题)
fillColor: feature.properties.value > 100 ? '#ff4d4f' : '#1677ff',
fillOpacity: 0.4,
};
},
// ② pointToLayer:Point 要素怎么渲染(默认是普通 marker)——换成圆/自定义图标
pointToLayer(feature, latlng) {
const mag = feature.properties.mag;
return L.circleMarker(latlng, { // 圆点标记(地震图标配)
radius: 4 + mag * 1.5, // 半径随震级
fillColor: mag >= 5 ? '#ff4d4f' : '#faad14',
color: '#fff', weight: 1, fillOpacity: 0.9,
});
},
// ③ onEachFeature:每个要素绑交互(点击/悬停/弹窗)——要素级事件的标准位置
onEachFeature(feature, layer) {
const p = feature.properties;
layer.bindPopup(`<b>${p.place}</b> M${p.mag}`);
layer.on('mouseover', () => layer.setStyle({ weight: 4 }));
layer.on('mouseout', () => layer.setStyle({ weight: 2 })); // 悬停高亮:setStyle 即时生效
layer.bindTooltip(p.name, { direction: 'top' });
},
// ④ filter:只要一部分要素
filter: (feature) => feature.properties.mag >= 3,
});
layer.addTo(map);
心智模型:L.geoJSON(数据, 配置) = "声明式地把 GeoJSON 变成图层"。三大回调分别接管样式、点形态、交互——数据不变回调不变,换数据就重建图层。
三、数据驱动渲染的完整模式(真实项目流程)
// ① fetch 远端 GeoJSON(模块 02 的技能)
const res = await fetch('https://geo.datav.aliyun.com/areas_v3/bound/100000_full.json'); // 全国省界
const provinces = await res.json(); // DataV 出厂即 4326 GeoJSON(CORS 开放)
const quakesRes = await fetch('https://earthquake.usgs.gov/earthquakes/feed/v1.0/summary/all_day.geojson');
const quakes = await quakesRes.json(); // USGS 当日地震(CORS 开放)
// ② 各自渲染成图层(省界:细边框面;地震:circleMarker)
const provinceLayer = L.geoJSON(provinces, { style: {...}, onEachFeature: {...} }).addTo(map);
const quakeLayer = L.geoJSON(quakes, { pointToLayer: {...} }).addTo(map);
// ③ 更新 = 重建或 setData(第 13 节"数据变了就重画"的 Leaflet 版)
quakeLayer.clearLayers().addData(newData); // 原地更新(保留图层引用/事件)
// 或干脆 map.removeLayer(old); L.geoJSON(new).addTo(map); (简单粗暴版)
四、动手跟练:05 · 省界 + 地震点渲染
配套文件:05-leaflet/examples/05-省界+地震点渲染.html(需联网;两个数据源都开放 CORS,直接 fetch)
步骤:
- 底图 + 全国省界 GeoJSON(DataV)渲染:浅色填充 + 悬停高亮 + 点击弹省名
- 叠加 USGS 当日地震:circleMarker 半径随震级、颜色分级(<4 黄 / ≥5 红)、Popup 详情(含"xx 小时前"——dayjs 可选)
- 完成 6 个 TODO:省界悬停高亮(setStyle/setStyle 恢复——注意存原始样式)、点击省弹出省名与"adcode"、地震按时间过滤按钮(重建图层)、数据加载失败兜底(catch + 界面提示)、图层顺序(quakeLayer 在上——pane 概念预告第 07 节)、用一个 select 切换"全部/仅 M5+"(filter 重建)
- 体验时刻:打开这个页面 = 一张"中国行政区划 + 全球当日地震"专题地图——你已经做出真实产品级的东西了
通关标准:
- 三大回调全部亲手实现
- 两个真实数据源 fetch 渲染成功
- 过滤重建与加载兜底齐备
五、自测题
- 三大回调分别接管什么?每个的调用时机?
- pointToLayer 不配时 Point 渲染成什么?
- 悬停高亮的实现模式(含恢复)?
- 图层更新的两种方式与取舍?
- DataV GeoAtlas 与 USGS 两个数据源在坐标系与格式上的共同点?
参考答案
- style=线面样式(每要素调用);pointToLayer=点的渲染形态;onEachFeature=交互绑定。都在图层创建/每要素处理时调用。
- 默认普通 marker(蓝水滴)。
- mouseover 里 setStyle 高亮,mouseout 恢复(恢复值要么写死要么提前存 layer.options 原样式)。
- clearLayers()+addData 原地更新(保留引用与绑定);removeLayer+新建(简单粗暴)。交互频繁选前者。
- 都是 WGS84 标准 GeoJSON 且开放 CORS——"交换格式用 4326 GeoJSON"的直接受益者。
六、下一步
数据上地图了 → 第 06 节:事件与交互,把"用户的每一次点击"系统化。