Fork me on GitHub

mapbox离线使用

mapbox 是一个美国的地图服务供应商,在地图领域技术上是非常领先的。当时对于公司内部想使用 mapbox,但是又是服务于内网客户,于是研究了下mapbox的离线部署方案,这里做个记录,但是mapbox还在高速更新迭代中,这是基于当前能实现的一个方案,后面如果还在使用mapbox,或者继续研究的话,在继续记录吧。

mapbox-gl 介绍

mapbox是目前地图领域很领先的一家公司,已为 Foursquare、Pinterest、Evernote、金融时报、天气频道、优步科技 等公司的网站提供了订制在线地图服务。Mapbox 是一些开放源代码地图库及应用程序的创建者或最大的贡献者,其中包含了MBTiles 规范、TileMill 制图 IDE、Leaflet JavaScript 库,以及 CartoCSS 地图格式化语言与语法分析器等。对于web端前端 GIS渲染引擎是Mapbox GL JS。由于公司项目处于内网环境,无法访问mapbox的地图服务,因此需要对mapbox进行本地化,以满足公司项目的需求。

https://www.mapbox.com/

mapbox-gl 自定义样式

  • mapbox样式主要包括以上几个参数:
  • version:JS SDK对应版本必须为8,
  • name:样式的命名,
  • sprite:雪碧图,将一个地图涉及到的所有零星图标图片都包含到一张大图中。
  • glyphs:.pbf格式的字体样式,例如微软雅黑等字体库。
  • sources:图层的资源文件,可以支持矢量切片、栅格、dem栅格、图片、geojson、视频等格式
  • layers:是对每个图层样式的描述,这里就是对地图样式渲染的关键,可以做定制化地图样式。
    具体参数及其api可以参考mapbox官网。

离线部署

mapbox-gl.js,mapbox-gl.css离线部署

只需要从官网下载mapbox-gl.js,mapbox-gl.css到本地即可。

glyphs字体本地化

mapbox需要的字体为.pbf格式字体,可能很多人对于.pbf文件不太了解,在此介绍一下.pbf文件,.pbf文件的全称为Protocol Buffers,是Google公司开发的一种数据描述语言,类似于XML能够将结构化数据序列化,可用于数据存储、通信协议等方面。简单来说就是结构简单、速度快,和JSON之间的对比可以参考使用 Protocol Buffers 代替 JSON 的五个原因。

字体

上面是微软雅黑的pbf字体库,如果想将把otf和ttf字体转换为Mapbox GL使用的protobuf格式的DF字体,可以使用mapbox开源的字体转换工具node-fontnik,具体使用方法可以参考官方文档

sprite本地化

访问mapbox地图服务我们可以从网络请求中查看官方样式中的sprite

sprite

同时还有一个sprite.json数据,用来描述sprite雪碧图

spriteJson

另外,需要更加地图zoom可能需要不同大小的sprite图片,为此mapbox用@2x,@3x等等分别表示2倍,3倍大小。

sprite@2json

了解了mapbox是sprite原理以后,其本地化所要做的工作是将小图标合成一张sprite大图并在sprite.json中记录生成的位置信息,这里最主要的就是图标的摆放规则。

地图样式编写

首先,将sprite,glyphs替换为本地环境。

1
2
3
4
5
{
"version": 8,
"sprite": "http://172.16.43.88:8082/sprites/sprite",
"glyphs": "/assets/fonts/{fontstack}/{range}.pbf",
}

其中fontstack代表字体文件夹名称,range代表当前字体文件名称(mapbox会根据当前zoom和地图自自动匹配)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
{
"layout": {
"text-field": "{name}",
"text-font": [
"Microsoft YaHei",
],
"symbol-placement": "line",
"text-pitch-alignment": "viewport",
"text-max-angle": 30,
"text-size": {
"base": 1,
"stops": [
[
13,
12
],
[
18,
16
]
]
}
},
}

text-font下的Microsoft YaHei 为字体文件夹名称

其次,需要添加sources,sources为geoserver返回的地图数据。

1
2
3
4
5
6
7
8
9
10
11
12
{
"sources": {
"waterways": {
"type": "vector",
"scheme": "tms",
"tiles": [
"http://172.16.43.88:8088/geoserver/gwc/service/tms/1.0.0/chinamap%3Agis_osm_waterways_free_1@EPSG%3A900913@pbf/{z}/{x}/{y}.pbf"
]
}
...
}
}

这里的 http://172.16.43.88:8088/geoserver/gwc/service/tms/1.0.0/chinamap%3Agis_osm_waterways_free_1@EPSG%3A900913@pbf 是Geoserver 发布的tms服务,获取的矢量切片

之前我们在geoserver中添加了waterways的图层,也介绍了geoserver服务能力及其tiles链接规范,我们就可以在sources中添加,type代表类型,我们是矢量切片选择vector,使用的是tms服务。下面我们看看如何编写waterways的样式。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
{
//waterway
{
"id": "waterway",
"type": "line",
"source": "waterways",
"source-layer": "gis_osm_waterways_free_1",
"filter": [
"all",
["==", "$type", "LineString"],
["in", "fclass", "canal", "river"]
],
"layout": {"line-join": "round", "line-cap": "round"},
"paint": {
"line-color": "hsl(209, 18%, 20%)",
"line-width": [
"interpolate",
["exponential", 1.3],
["zoom"],
8.5,
2,
20,
15
],
"line-opacity": [
"interpolate",
["linear"],
["zoom"],
8,
0,
8.5,
1
]
}
}
}

需要注意的是filter需要根据数据库字段进行筛选,其他具体可以看mapbox官方文档。
具体其他相关操作mapbox官网有相关的demo

https://docs.mapbox.com/mapbox-gl-js/api/

坚持原创技术分享,您的支持将鼓励我继续创作!