4. 地图初始化:创建地图实例,设置中心点与缩放级别,添加底图图层
地图初始化,说白了就是给无人机画一张「底图」。没有这张底图,航迹可视化就是空中楼阁。我刚开始做无人机地面站的时候,觉得这步太简单了,不就是new一个Map对象嘛?结果第一次跑起来,地图一片灰,连个瓦片都没加载出来……嗯,后来才发现是图层没加上。
这一节,我们就把地图初始化这件事拆清楚。你跟着我走一遍,以后不管换什么地图库,思路都一样。
4.1 核心概念:地图实例、中心点、缩放级别、底图图层
先理清四个基本概念。它们之间的关系,我用一张图给你讲明白。
- 地图实例:整个地图的容器,所有操作都挂在这个对象上。
- 中心点:地图打开时,屏幕正中央对应的经纬度坐标。
- 缩放级别:数字越大,看得越细。一般0-18级,0级看全球,18级看街道。
- 底图图层:瓦片地图的来源,比如卫星图、街道图、地形图。
4.2 创建地图实例
我用的是 Leaflet,轻量、开源、文档好。你如果用过其他库,思路完全一样。
先引入 Leaflet 的 CSS 和 JS 文件。我个人习惯用 CDN,省事。
<!-- 在 <head> 中引入 CSS -->
<link rel="stylesheet" href="https://unpkg.com/leaflet@1.9.4/dist/leaflet.css" />
<!-- 在 <body> 底部引入 JS -->
<script src="https://unpkg.com/leaflet@1.9.4/dist/leaflet.js"></script>
然后需要一个容器 div,给个 id,设好宽高。
<div id="map" style="width: 100%; height: 600px;"></div>
接下来,创建地图实例。代码就一行:
const map = L.map('map', {
center: [39.9042, 116.4074], // 北京天安门
zoom: 13
});
我的习惯:创建实例时就把 center 和 zoom 传进去,一步到位。当然你也可以先 new 一个空地图,后面再 setView()。但我建议你一次搞定,少写一行是一行。
4.3 设置中心点与缩放级别
中心点用经纬度数组表示,格式是 [纬度, 经度]。注意顺序,先纬度后经度。我见过有人写反了,地图直接飞到非洲去了……
缩放级别是个整数。无人机航迹可视化一般用 13-17 级。13 级看城市,15 级看街区,17 级看楼栋。
如果你需要动态调整,可以用这两个方法:
// 设置中心点,不改变缩放级别
map.setView([39.9042, 116.4074]);
// 同时设置中心点和缩放级别
map.setView([39.9042, 116.4074], 15);
// 只改变缩放级别
map.setZoom(16);
注意:setView() 和 setZoom() 会触发地图重新渲染。如果你在循环里频繁调用,性能会崩。我曾经在实时航迹更新时每秒钟 setView 一次,结果地图卡成幻灯片。后来改用 flyTo() 加动画过渡,体验好很多。
4.4 添加底图图层(TileLayer)
底图图层是地图的「皮肤」。没有它,地图就是一片灰。我刚开始做的时候忘了加 TileLayer,调试了半天,还以为代码写错了……
TileLayer 的核心参数是 URL 模板。瓦片服务器把地图切成很多小方块,按 z/x/y 的规则拼接。比如 OpenStreetMap 的瓦片地址是:
const tileLayer = L.tileLayer('https://tile.openstreetmap.org/{z}/{x}/{y}.png', {
maxZoom: 19,
attribution: '© <a href="https://www.openstreetmap.org/copyright">OpenStreetMap</a>'
});
tileLayer.addTo(map);
也可以链式调用,一步到位:
L.tileLayer('https://tile.openstreetmap.org/{z}/{x}/{y}.png', {
maxZoom: 19,
attribution: '© OpenStreetMap contributors'
}).addTo(map);
4.5 完整的初始化代码
把上面三步合起来,就是一份完整的地图初始化代码:
<!DOCTYPE html>
<html>
<head>
<link rel="stylesheet" href="https://unpkg.com/leaflet@1.9.4/dist/leaflet.css" />
</head>
<body>
<div id="map" style="width: 100%; height: 600px;"></div>
<script src="https://unpkg.com/leaflet@1.9.4/dist/leaflet.js"></script>
<script>
const map = L.map('map', {
center: [39.9042, 116.4074],
zoom: 13
});
L.tileLayer('https://tile.openstreetmap.org/{z}/{x}/{y}.png', {
maxZoom: 19,
attribution: '© OpenStreetMap contributors'
}).addTo(map);
</script>
</body>
</html>
核心要点:
- 地图实例、中心点、缩放级别、底图图层,四者缺一不可。
- 中心点格式:[纬度, 经度],先纬度后经度。
- 缩放级别:无人机航迹一般用 13-17 级。
- 底图图层:使用 TileLayer,URL 模板格式为
{z}/{x}/{y}。
4.6 常见问题与避坑
| 问题 | 原因 | 解决方法 |
|---|---|---|
| 地图一片灰 | 没有添加 TileLayer | 检查是否调用了 addTo(map) |
| 地图显示在非洲 | 经纬度顺序写反了 | 确认是 [纬度, 经度] 格式 |
| 瓦片加载慢 | 网络问题或瓦片服务器限流 | 换用国内镜像或离线瓦片 |
| 地图容器高度为0 | div 没有设置高度 | 给 div 设置 height 或 min-height |
我的经验:调试时可以在浏览器控制台输入
map.getCenter() 和 map.getZoom(),实时查看当前中心点和缩放级别。这个习惯帮我省了不少排查时间。
地图初始化到这里就完成了。你想想看,其实就三步:创建实例、设置位置、添加图层。后面我们做航迹可视化,都是在这张底图上叠加数据。底图稳了,后面的事就好办了。