TL;DR:智慧水利平台第一页那张地图,本质是「底图 + 线状河流 + 点状工程 + 面状范围」四层叠加。本文基于 Leaflet 1.9.4 + Vue3 + Vite,用深圳 mock 数据跑通最小可运行版本。
水利一张图是什么
把物理世界的水利对象按空间位置画到电子地图上,三类要素:
| 类型 | 业务对象 | Leaflet API |
|---|---|---|
| 线状 | 河流、堤防、渠道 | L.polyline |
| 点状 | 水库、水闸、雨量站、水位站 | L.marker / L.circleMarker |
| 面状 | 蓄滞洪区、河湖管理范围 | L.polygon |
💡 选型 :正式项目常用 SuperMap / MapGIS / OpenLayers,但展示型一张图、轻量大屏、H5 移动端,Leaflet 足够------gzip 后 ~40KB,开源免费,手势原生。
第一步:起一张底图
纯 HTML 版本(CDN)
map.html
html
<link rel="stylesheet" href="https://unpkg.com/leaflet@1.9.4/dist/leaflet.css" />
<div id="map" style="height: 600px"></div>
<script src="https://unpkg.com/leaflet@1.9.4/dist/leaflet.js"></script>
init.js
javascript
// 中心 [纬度, 经度],缩放级别 11(深圳市民中心)
const map = L.map('map').setView([22.5431, 114.0579], 11)
// 深色底图:国内推荐 ArcGIS,OSM 加载慢
L.tileLayer(
'https://server.arcgisonline.com/ArcGIS/rest/services/Canvas/World_Dark_Gray_Base/MapServer/tile/{z}/{y}/{x}',
{ attribution: '© Esri' }
).addTo(map)
⚠️ 国内瓦片坑:不要用 OSM,加载慢且偶尔超时。ArcGIS Dark Gray 在国内可访问,配色也适合大屏。
Vue3 + Vite 版本
bash
npm create vite@latest leafletjs-demo -- --template vue
cd leafletjs-demo
npm install leaflet
src/main.js
javascript
import { createApp } from 'vue'
import App from './App.vue'
import 'leaflet/dist/leaflet.css'
createApp(App).mount('#app')
src/views/Demo01.vue
vue
<template>
<div ref="el" class="demo-map"></div>
</template>
<script setup>
import { ref, onMounted, onUnmounted } from 'vue'
import L from 'leaflet'
const el = ref(null)
let map = null
onMounted(() => {
map = L.map(el.value).setView([22.5431, 114.0579], 11)
L.tileLayer(
'https://server.arcgisonline.com/ArcGIS/rest/services/Canvas/World_Dark_Gray_Base/MapServer/tile/{z}/{y}/{x}',
{ attribution: '© Esri' }
).addTo(map)
})
onUnmounted(() => map?.remove())
</script>
<style scoped>
.demo-map { position: absolute; inset: 0; }
</style>
⚠️ flex 布局坑 :父容器是 flex 时,
.demo-map { height: 100% }会因为父链高度断裂而塌成 0,地图不显示。改成position: absolute; inset: 0最稳。
第二步:画水利要素
河流(Polyline)
javascript
// 深圳河(示意坐标)
L.polyline([
[22.528, 114.045], [22.522, 114.062], [22.515, 114.078],
[22.508, 114.095], [22.500, 114.112]
], { color: '#1976d2', weight: 3 })
.addTo(map)
.bindTooltip('深圳河')
水库(Marker + 自定义图标)
用 divIcon 画水坝 SVG,比默认蓝点专业:
javascript
const reservoirIcon = L.divIcon({
html: `<svg width="22" height="22" viewBox="0 0 22 22">
<rect x="3" y="7" width="16" height="10" fill="#01579b" stroke="#fff" stroke-width="1.5" rx="2"/>
<path d="M6 7 L9 3 L13 3 L16 7" fill="none" stroke="#fff" stroke-width="1.5"/>
</svg>`,
iconSize: [22, 22],
iconAnchor: [11, 11],
className: ''
})
L.marker([22.584, 114.148], { icon: reservoirIcon })
.addTo(map)
.bindPopup('<b>深圳水库</b><br/>中型 · 罗湖区')
点击读经纬度
javascript
map.on('click', (e) => {
const { lat, lng } = e.latlng
console.log(`纬度 ${lat.toFixed(6)},经度 ${lng.toFixed(6)}`)
})
效果预览

⚠️ 三个必踩的坑
1. 地图容器没高度。 Leaflet 容器不会自己撑高,父链任何一环没显式高度就是空白。flex 布局下尤其常见,用 position: absolute; inset: 0 解决。
2. 坐标顺序写反。 Leaflet 所有点坐标都是 [纬度, 经度],但 GeoJSON、CAD 成果给的是 [经度, 纬度]。写反的结果是点全跑非洲去了。
3. 坐标系偏移。 Leaflet 原生只认 Web 墨卡托(EPSG:3857),国内正式数据是 CGCS2000 / GCJ-02,直接叠点位会偏移几百米。下一篇专门讲。
小结
| 要素 | API | 一句话 |
|---|---|---|
| 底图 | L.tileLayer |
瓦片 URL 模板 {z}/{x}/{y} |
| 线状 | L.polyline |
河流堤防 |
| 点状 | L.marker |
水库测站 |
| 交互 | bindPopup / bindTooltip |
挂业务信息 |
📦 本文是《智慧水利 GIS 实战》系列第 1 篇,完整 Vue3 demo(10 个场景)见仓库
leafletjs-demo/目录,npm run dev即可跑。