使用Tileserver-GL+MapLiberGL+OSM创建自己的地图
前言
近期,突发奇想,因为学校的地图并不太直观,要么细节数据不全,要么操作很难,需要点击多级才可以进入查看
因此,决定自己动手创建一份地图,方便日常使用
最后在询问了 AI 之后,决定使用 Tileserver-GL+MapLiberGL+OSM 来创建自己的地图
部署 Tileserver-GL
安装 Tileserver-GL
根据官方的教程, 使用 docker 来安装 Tileserver-GL 是最为便捷的
但是,官方并没有说明后期需要导入数据的时候应该如何操作,我在这里也踩了很多坑
最后,我根据自己的情况,写了一个docker-compose.yml文件,内容如下,可以参考一下:
1 |
|
其中,ports 部分是将容器的 8080 端口映射到宿主机的 8080 端口
volumes 部分是将宿主机的相关目录挂载到容器中
在我的环境中,/home/u0_a244/TileServer-GL/ 是我用来存放 Tileserver-GL 相关文件的目录,数据如下:
1 |
|
请根据自己的实际情况,修改 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 目录下
获取 Tileserver-GL 样式文件
虽然默认直接启动,它是会自动加载自带的样式文件的,但是因为调整不方便,而且并不是很好看,我就选择了使用其他的 style 文件
我是在 Maputnik 上的左上角找到了一个叫做 OSM Liberty 的样式文件,预览后觉得还可以,就点击左上角的 Save 按钮下载
但是,由于各个文件的渲染逻辑不同,为了不渲染出现问题,需要对样式文件进行一些修改
修改名称读取
打开下载下来的 osm-liberty.json 文件,ctrl+f找到 name 部分,将某些的 name:latin 进行修改
具体是怎么改,还是要看回去上一节中 process-openmaptiles.lua 文件中 language 变量的设置
比如我设置的是:
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 标签)
所以,我就应该把全部 name:latin 改成 name,因为生成的文件根本就没有 name:latin 标签
修改地图路径
在样式文件中,通常都会直接指定地图 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 功能来渲染这些数据,效果还不错








