使用Tileserver-GL+MapLiberGL+OSM创建自己的地图
前言
近期,突发奇想,因为学校的地图并不太直观,要么细节数据不全,要么操作很难,需要点击多级才可以进入查看
因此,决定自己动手创建一份地图,方便日常使用
最后在询问了 AI 之后,决定使用 Tileserver-GL(后端底图)+ MapLiberGL(前端显示+POI叠加层)+ OSM(数据源) 来创建自己的地图
部署 Tileserver-GL
安装 Tileserver-GL
根据官方的教程, 使用 docker 来安装 Tileserver-GL 是最为便捷的
但是,官方并没有说明后期需要导入数据的时候应该如何操作,我在这里也踩了很多坑
最后,我根据自己的情况,写了一个 docker-compose.yml文件,内容如下,可以参考一下:
1 | services: |
其中,ports 部分是将容器的 8080 端口映射到宿主机的 8080 端口
volumes 部分是将宿主机的相关目录挂载到容器中
在我的环境中,/home/u0_a244/TileServer-GL/ 是我用来存放 Tileserver-GL 相关文件的目录,数据如下:
1 | ~/TileServer-GL$ tree -L 2 |
请根据自己的实际情况,修改 docker-compose.yml 中的路径
至于这些文件是怎么来的,后面会讲到
修改配置文件
在前面的 docker-compose.yml 文件中,我挂载了一个 config.json 文件,这个文件就是用来配置 Tileserver-GL 的配置
相关的文档可以在官网找到
我这里使用的配置文件为:
1 | { |
这里重点需要修改的是 domains部分,将 my-domain:8080 修改为你自己的域名或者 IP 地址加端口号,否则无法正常请求,另外根据文档所述,还能在访问的时候达到负载均衡的效果(挂载到服务器用的时候绝对不能写成 localhost)
此外,mbtiles 部分需要修改为你自己的 mbtiles 文件名(因为我在文件上方已经说明了 mbtiles 是在 data 目录下的,所以就不用再写 data/ 了)
styles 部分是用来配置样式文件的,也需要改成自己的样式文件名,后面会讲到如何获取和修改样式文件
获取 mbtiles 数据
Tileserver-GL 需要 mbtiles 格式的数据才能运行,获取 mbtiles 数据有很多种方式,这里介绍两种比较常用的方式
方式一:BBBike 下载
BBBike 是一个提供地图数据下载的网站,支持多种格式的地图数据下载,包括 mbtiles 格式
- 访问 BBBike 官网
- 在地图上选择你需要的区域,可以通过搜索城市名称来快速定位
- 选择输出格式为 mbtiles
- 提交下载请求,填入邮箱,等待 10 分钟左右处理完成后下载 mbtiles 文件
这个方式的优点是简单快捷,适合下载小范围的地图数据
但是因为地图的生成方式不是自己控制的,后续在数据处理和渲染的时候会遇到不少问题
这部分我会在渲染样式的时候讲到
方式二:使用 MapTiler 下载
MapTiler 官方提供了数据下载,可以直接访问 MapTiler 数据下载页面,选择区域下载即可
但是它的免费数据下载有一些限制:
- OpenStreetMap Vectors (2020)
- Satellite Low-Res (2016)
- Non-commercial
反正我是觉得 2020 年的数据有点旧了,而且所以就没有选这个
方式三:使用 OSM 数据 + tilemaker 自己生成 mbtiles
- 下载 OSM 数据,可以从 Geofabrik 下载所需区域的 PBF 文件
- 安装 tilemaker,可以参考 tilemaker 的 GitHub 页面
其实,如果并不在意程序的最新版本的话,可以直接在GitHub的 Releases 页面下载编译好的二进制文件但是需要注意的是,Windows 下的 v3.0.0 版本是有问题的,Windows用户 建议下载 v2.4.0 版本
另外,还需要下载配置文件 config-openmaptiles.json 和处理脚本 process-openmaptiles.lua,可以从该仓库的 resources 目录中获取
- 使用 tilemaker 将 PBF 文件转换为 mbtiles 文件,实例命令如下:
1 | tilemaker --input "guangdong-260113.osm.pbf" --output "guangdong.mbtiles" --config .\config-openmaptiles.json --process .\process-openmaptiles.lua |
其中,--input 指定输入的 PBF 文件,--output 指定输出的 mbtiles 文件,--config 和 --process 分别指定配置文件和处理脚本,需要自己替换成实际的文件路径
如果想裁切数据,可以使用 --bbox 参数,格式为 minLon,minLat,maxLon,maxLat,例如:
1 | tilemaker.exe --input "guangdong-260113.osm.pbf" --bbox 113,22.34,114,22.50 --output "guangdong.mbtiles" --config .\config-openmaptiles.json --process .\process-openmaptiles.lua |
还有值得注意的是,process-openmaptiles.lua 文件开头的几个带 language 的变量需要根据自己后面的 style.json 文件来决定,否则可能会导致某些标签无法显示,我后面会再次提到
然后打完这个命令之后,等待一段时间(我生成一个学校的大小用时大概为 30s, 使用 i7-12700H CPU,占用 5.5GB 内存),就可以得到一个 mbtiles 文件了
最后记得将它移动到 Tileserver-GL 的 data 目录下
但是这个方法也有一定的缺点(相对于 Maptiler 提供的文件来说),因为它经过一次转换,例如 building:part 之类的细节就会被去掉,没法准确的渲染出来 3D 效果
另外,这个图也解释了为什么无法直接从平台 Geojson 变成 Tileserver-GL 样式渲染需要的格式:它是分为右侧那几大类来分类渲染,普通 Geojson 是没分类的,会导致无法识别类型而对应不上样式
至于有没有方法可以从普通的在 Overpass 上获得的 Geojson 转化为这个分类的格式,再用 osmium-tool 之类的转为 mbtiles呢?或许是有机会的,但是我似乎没有找到,如果有找到的话可以在评论区提一下
方法四:使用 OpenMapTiles 构建完整数据集
这个是官方推荐的方法,使用 OpenMapTiles 工具链来生成完整的地图数据集,但是部署的文件相当复杂,会变得非常慢
可以参考官方 GitHub 仓库的 README 文档来进行操作
如果需要裁切之前的整个 PBF 为特定区域的数据,可以使用 OSMconvert 来操作,链接里面直接下载二进制文件就行了,然后使用以下命令来裁切数据,经纬度可以使用 Bounding Box Tool 来获取
(这是我在 Windows 下的命令,其他系统请自行参照文档更改)
1 | .\osmconvert64-0.8.8p.exe .\guangdong-260113.osm.pbf -b="113.4,22.3,114.5,22.6" -o="guangdong.osm.pbf" |
然后将下载好的 pbf 放进 OpenMapTiles 的 data 目录下,根据文档走一次,就可以生成一个完整的 mbtiles 文件了
以下内容截取自 GitHub 仓库的 README 文档,有些我标了 optional 的没有需要就可以跳过:
1 | make clean # clean / remove existing build files |
实测以我老笔记本 i7-2677M + SSD 的配置,生成一个学校的范围就部署了将近 5 个小时(因为主力机没装 Linux,没法跑 make)
主要卡在 SSD 的 I/O 写入瓶颈上,因为总共会生成多个 Docker Container,产生大量的写入
建议使用高速的 M.2 NVMe SSD 来进行操作
第二次跑似乎就快点了,0.05 的经度和 0.03 的纬度范围大概跑了 20 分钟,跑出来的文件大小在 500KB 左右
然后我又试了下我 Azure 的 1 年免费 VPS(2C1G + 64G Premium SSD,开了 2G 的 Swap),跑了就大概 5 分钟,读写平均上到了 70MB/s,可以根据自己的硬件情况来预估时间
另外服务器上部署要注意的是,HDD 的服务器几乎完全不能部署,性能都不太行,跑几分钟还不够我笔记本上跑几秒
获取 Tileserver-GL 渲染样式文件
虽然默认直接启动,它是会自动加载自带的样式文件的,但是因为调整配置不方便,而且并不是很好看,我就选择了使用其他的 style 文件
我是在 Maputnik 上的左上角找到了一个叫做 OSM Liberty 的样式文件,预览后觉得还可以,就点击左上角的 Save 按钮下载
但是,由于各个文件的渲染逻辑不同,为了不渲染出现问题,需要对样式文件进行一些修改
修改名称读取
打开下载下来的 osm-liberty.json 文件,ctrl+f找到 name 部分,将某些的 name:latin 进行修改
具体是怎么改,还是要看回去上一节中 process-openmaptiles.lua 文件中 language 变量的设置
比如我在上面的 lua 设置的是:
1 | -- Preferred language can be (for example) "en" for English, "de" for German, or nil to use OSM's name tag: |
这个设置就决定在前面生成 mbtiles 的时候,将 OpenStreetMap 中的 name 标签写入 name 属性中,name:zh 标签写入 name:zh 属性中,name:en 标签写入 name:en 属性中 (理论上是,但是不知道为什么我生成的文件中并没有 name:zh 标签)
我这样改是为了避免歧义,反正默认操作会在生成 mbtiles 的时候把中文写入 name:latin标签,听起来逻辑怪怪的
所以,我就应该把全部 name:latin 改成 name,因为生成的文件根本就没有 name:latin 标签
另外,如果不是用 maputnik 转换生成文件的话(即不是用上面的方法3),具体应该写什么可以先跳过这部分,先启动一次 Tileserver-GL,在网页下方的 Data 选项卡的 Inspect 按钮,点进去随机看几个 POI,看文件里面究竟写了什么字段
示例:
如上图,我写的就是下面这样,来同时支持中文和英文的显示
1 | "text-field": [ |
修改地图路径
在样式文件中,通常都会直接指定地图 tiles 的路径,但是这个也可以通过引用 config.json 文件中的数据源来读取
比如我就写成了
1 | "sources": { |
这样就可以直接引用 config.json 文件中 data 部分的 openmaptiles 数据源了
如果你的 config.json 文件中 data 部分的名称不是 openmaptiles 的话,需要相应地修改这里的名称
修改字体
默认字体是无法显示中文的,所以需要修改字体
首先是下载字体,我这里使用的是 MiSans ,先获取到字体的 ttf 或者 otf 文件
然后,需要用特殊的工具将字体转换为 PBF 格式
可以使用 font-maker 这个网站来转换
也可以使用 fonts 这个工具来转换
效果应该都差不多的
转换完成后,将生成的存有 pbf 文件夹整个放到 Tileserver-GL 的 fonts 目录下
最后,修改样式文件中的字体引用,找到以下位置修改:
1 | "glyphs": "{fontstack}/{range}.pbf", |
此外,还需要搜索整个文件,找到带有 text-font 的地方,将字体名称修改为你刚才转换的字体文件夹的名称
例如我写的是 "text-font": ["MiSans Semibold"],
启动 Tileserver-GL
完成以上步骤后,就可以启动 Tileserver-GL 了
在 Tileserver-GL 目录下,运行以下命令:
1 | docker-compose up -d |
然后,打开浏览器,访问 http://your-domain:8080 (将 your-domain 替换为你的域名或者 IP 地址),就可以看到自己的地图了
创建前端 html 页面
最后,如果想要创建一个前端的 html 页面来展示地图,可以参考以下代码:
1 |
|
这里的 style 地址需要修改为你自己的 Tileserver-GL 的样式地址,建议使用 https 来避免跨域问题
后面再在上方加 POI 标记、自定义画线什么的,参照 MapLibre GL JS 官方文档 就可以了,或者问 AI 也行,实测错误率不高
反正我后面使用的 Overpass API 来获取 POI 数据,然后使用 MapLibre GL JS 的 Marker 功能来渲染这些数据,效果还不错
结语
以上就是使用 Tileserver-GL + MapLiberGL + OSM 创建自己的地图的详细教程
希望对大家有所帮助,如果有任何问题,欢迎在评论区留言讨论!
参考资料
- Tileserver-GL 官方文档
- MapLibre GL JS 官方文档
- Expressions | Mapbox Style Spec | Mapbox Docs | Mapbox
- OpenMapTiles 官方文档
- OpenMapTiles GitHub
- 自建OpenStreetmap地图瓦片服务 | Sparktour’s Blog
- Tippecanoe GitHub (用来 GeoJSON 生成 mbtiles 的,但是因为 layer 样式对不上用不了)
- 简单地图应用-开源地图OpenStreetMap仿Mapbox样式部署本地矢量瓦片(上)一、引言近期在实验性质的做自己 - 掘金
- Create custom map extract - OpenMapTiles
- Osmconvert - OpenStreetMap Wiki (OSMconvert 用来裁切 PBF 数据)
- openstreetmap - How to clip a .osm.pbf file to a shapefile in R - Geographic Information Systems Stack Exchange
- BBBike extracts OpenStreetMap (OSM,Garmin,Shapefile etc.)
- Maputnik (在线样式编辑器)
- font-maker (在线字体转换工具)







