03-从一个点到一张图:Leaflet 加载水利对象 GeoJSON 实战

从一个点到一张图:Leaflet 加载水利对象 GeoJSON 实战

TL;DR :几十上百个水库、堤防、水闸怎么批量上图?一份 GeoJSON(点线面 + properties)+ L.geoJSON 三个回调搞定,还能按类型自动换样式、做图层开关。


水利对象在 GeoJSON 里长什么样

水利一张图管的对象正好对应 GeoJSON 三种几何:点 (水库、水闸、测站)、线 (河流、堤防)、面 (蓄滞洪区、管理范围)。业务档案放在 properties 里:

water-features.geojson

json 复制代码
{
  "type": "FeatureCollection",
  "features": [
    {
      "type": "Feature",
      "geometry": { "type": "Point", "coordinates": [114.148, 22.584] },
      "properties": { "name": "深圳水库", "type": "reservoir", "capacity": 46 }
    },
    {
      "type": "Feature",
      "geometry": {
        "type": "LineString",
        "coordinates": [[114.045, 22.528], [114.062, 22.522], [114.078, 22.515]]
      },
      "properties": { "name": "深圳河", "type": "river" }
    }
  ]
}

⚠️ 坐标顺序 :GeoJSON 标准规定坐标是 [经度, 纬度],而 Leaflet 全用 [纬度, 经度]。这个方向问题最容易踩。


三行渲染:按类型自动换样式

把数据交给 L.geoJSON,三个回调解决三件事:style 决定怎么画线面,pointToLayer 决定点怎么画,onEachFeature 决定弹什么:

javascript 复制代码
L.geoJSON(waterFeatures, {
  // 线/面:按对象类型上色
  style: (f) => {
    if (f.properties.type === 'river')
      return { color: '#1976d2', weight: 3 }
    if (f.properties.type === 'embank')
      return { color: '#b45309', weight: 2, dashArray: '4' }
  },
  // 点:水库/水闸画成蓝色圆点
  pointToLayer: (f, latlng) => L.circleMarker(latlng, {
    radius: 6, color: '#1976d2',
    fillColor: '#42a5f5', fillOpacity: 0.8
  }),
  // 每个对象挂业务弹窗
  onEachFeature: (f, layer) => {
    const p = f.properties
    layer.bindPopup(`<b>${p.name}</b><br>类型:${p.type}`)
  }
}).addTo(map)

真实项目里数据是接口吐的,前面加个 fetch 就是完整流程:数据底板服务返回 GeoJSON → 前端渲染 → 业务弹窗。


一张图标配:对象分组、图层开关

业务人员经常要「只看水库、藏掉河流」。把不同类型丢进不同图层组,交给右上角图层面板:

javascript 复制代码
// 按类型建两个图层组
const reservoirLayer = L.layerGroup()
const riverLayer = L.layerGroup().addTo(map)

// filter 按 properties.type 分流
L.geoJSON(waterFeatures, {
  filter: (f) => f.properties.type === 'reservoir'
}).addTo(reservoirLayer)

// 右上角图层面板
L.control.layers(null, {
  '水库 / 水闸': reservoirLayer,
  '河流 / 堤防': riverLayer
}).addTo(map)

⚠️ 三个坑

1. GeoJSON 坐标是 经度, 纬度,Leaflet 要 纬度, 经度。 标准规定,不是 Leaflet 的锅。前端自己拼 GeoJSON 时最容易写反。

2. properties 里别塞监测时序数据。 GeoJSON 只放对象档案(名称、类型、库容);实时水位、雨量这种高频变化数据,点弹窗时再单独请求接口,否则一个 GeoJSON 文件几十 MB,首屏卡死。

3. Polygon 首尾坐标要闭合。 蓄滞洪区这类面状要素,最后一个点要和第一个点相同。Leaflet 会帮你补,但其他服务端工具不一定。


小结

回调 作用
style 线/面按类型上色
pointToLayer 点用 circleMarker 而非默认图钉
onEachFeature 挂业务弹窗
filter 分流到不同图层组
L.control.layers 右上角开关面板

📦 本文是《智慧水利 GIS 实战》系列第 3 篇,完整代码见仓库 leafletjs-demo/。

相关推荐
Highcharts.js1 天前
Highcharts Orbit 完全指南:把每一张图表变成交互式分析工具
react.js·前端框架·highcharts·orbit·使用指南·ai 图表·交互式分析工具
总要学点什么2 天前
第96篇:三维数据加载-城市建筑白模样式+着色器——让色带按体量上色,最白的那档却涂不上去
前端·gis·webgl·cesium·着色器·空间分析·白模
总要学点什么3 天前
第97篇:三维数据加载-城市建筑白模自定义着色器——让一条光带沿高度扫上去,快慢却由帧率说了算
前端·gis·webgl·cesium·着色器·空间分析·白模
总要学点什么3 天前
第98篇:三维特效-材质线效果——给一条线换十种材质,虚线的图案只填了一半
开发语言·前端·javascript·ecmascript·gis·webgl·材质
我喜欢就喜欢4 天前
倾斜摄影 OSGB 进 Cesium 对不齐?先核 SRS、原点偏移和瓦片路径
gis·cesium·倾斜摄影·osgb·3d tiles
vjmap5 天前
MCP 实战:在 WorkBuddy 里一句话让 AI 生成红军长征地图动画(唯杰 AI 地图动画 MCP 接入教程)
aigc·gis·mcp
我才是银古6 天前
6 小时做一部 10 分钟纪录片:DeepSeek 4.1 Flash + DeepSeek Harness 的完整制片记录
gis·deepseek·dsh
vjmap7 天前
AI 智能体调用绘图工具画矢量地图:唯杰 AI 地图绘制上线,支持 MCP 接入 Cursor、Claude Code
gis·agent·mcp
多客:duokelijie7 天前
代练订单系统选型思路:跨品类游戏接入、订单分层管理、自动结算逻辑拆解!
数据库·mysql·微信小程序·前端框架·uni-app·php·持续部署
我喜欢就喜欢8 天前
点云 LAS/LAZ 按 shp 范围裁剪:PDAL pipeline、坐标系对齐与空洞检查
gis·点云·测绘·las·pdal