Mapbox显示GeoServer地图

前言

  最近做项目需要用到 Mapbox 这个地图可视化框架,以前也没用过,甲方有自己的地图数据,所以得结合 GeoServer 发布一下,简单记录一下流程。

发布篇

环境准备

  下载 GeoServer 以及同页面下的 Vector Tiles 插件,将插件中所有 jar 包都复制到 GeoServer 中webapps\geoserver\WEB-INF\lib目录下。在 bin 下执行 startup.bat 启动 geoserver,若需要修改端口,可修改 start.ini 文件中的jetty.port=8080,在浏览器中输入 http://localhost:8080/geoserver/web/,geoserver 中默认账号为admin,密码为geoserver,geoserver 中常用的两个坐标系为 EPSG:4326:wgs84坐标,Mercator 投影,EPSG:900913:wgs84 坐标,Web Mercator 投影,即保证投影为正方形,MapBox 中必须使用EPSG:900913坐标系统,900913 和 3857 是一样的坐标系统,在 PostGIS 中对应的 SRID 是 3857。

设置 Tile Caching

  Tile Layers 中可进行图层和图层组的预览,以及切片,在 seed/truncate 中可以设置切片类型以及自动将切片保存到 \data_dir\gwc 目录中。

  Caching Defaults 需要勾选 Enable TMS Service,以及在 Default Tile Image Formats for:中勾选 application/vnd.mapbox-vector-tile,其它默认即可。

Gridsets 设置新的坐标系统。

地图发布

在 数据 栏下:

  1. 点击工作区,添加新的工作区,命名以及填写 URI,勾选默认工作区。
  2. 点击数据存储,添加新的数据存储,选择数据源,以 Directory of spatial files (shapefiles) 为例,在连接参数下点击 浏览,选择shape文件存放目录,DBF 文件字符集选择 UTF-8 或 GBK。注: shape 文件名中不能有中文。
  3. 点击图层,添加新的资源,添加图层,选择上一步的添加的数据存储名称,点击发布或再次发布,进入发布配置界面,勾选 广告则会在 Layer Preview 中显示,一般不需要勾选,点击Compute from native bounds,GeoServer 会自动计算边框和经纬度信息,然后勾选Linear geometries can contain cicular arcs,使线性几何图形包含环形弧,然后保存。重复当前步骤,直到数据存储中所有图层都发布完毕。
  4. 点击图层组,添加新的图层组,添加图层,然后点击 生成边界,保存,即完成整个地图的发布。

在 Layer Preview 中点击 openLayers 进行地图预览,随意点击地图,若出现乱码,则需要在数据存储中修改 DBF 文件字符集。

Mapbox 访问 GeoServer 地图

  点击 Geoserver 的logo,然后点击 TMS 1.0.0协议,页面跳转后,查找需要访问的外部地址,即对应 TileMap 的 href 属性。MapBox 中访问发布好的切片服务需要在 http://localhost:8080/geoserver/gwc/service/tms/1.0.0/MapBoxTest:Test@EPSG:900913@pbf/{z}/{x}/{y}.pbf,即 href 属性值后面加上 /{z}/{x}/{y}.pbf ,同时注意 在 MapBox style 下 layers 中 source-layer 的值必须为图层名,这里为 "Test" (若使用图层组,则需要找到 Test 图层组下面的图层,使用对应图层名)。简单示例代码如下:

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
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
const mapStyle: mapboxgl.Style = {
version: 8,
sources: {
geoserverData: {
type: 'vector',
scheme: 'tms',
tiles: ["http://localhost:8080/geoserver/gwc/service/tms/1.0.0/MapBoxTest:Test@EPSG:900913@pbf/{z}/{x}/{y}.pbf"],
},

// 使用 OSM 数据源作为底图
// OsmTiles: {
// type: "raster",
// tiles: ["http://a.tile.openstreetmap.org/{z}/{x}/{y}.png"],
// tileSize: 256,
// },
},

layers: [
// 背景图层
{
id: 'background',
type: 'background',
paint: {
'background-color': "rgb(0, 0, 0)",
},
// interactive: true,
},

// {
// id: "OsmTiles",
// type: "raster",
// source: "OsmTiles",
// "source-layer": "osmtiles",
// },

// 道路
{
id: 'road',
source: 'geoserverData',
'source-layer': 'Test',

type: 'line',
layout: {
'line-cap': 'round',
'line-join': 'round',
},
paint: {
'line-width': {
base: 1.5,
stops: [
[5, 0.75],
[18, 32],
],
},
'line-color': 'rgb(255, 255, 255)',
},

interactive: true,
},

// 地图标注
{
id: 'label',
source: 'geoserverData',
'source-layer': 'Test',

type: 'symbol',
layout: {
'text-size': {
base: 1,
stops: [
[9, 10],
[20, 16],
],
},
'text-max-angle': 30,
'symbol-spacing': 250,
'text-font': ['Microsoft YaHei'], // 标注使用字体
'symbol-placement': 'line',
'text-padding': 1,
'text-rotation-alignment': 'map',
'text-pitch-alignment': 'viewport',
'text-field': '{name}', // 标注显示属性名
'text-letter-spacing': 0.01,
},
paint: {
'text-color': 'hsl(0, 0%, 0%)',
'text-halo-color': 'hsla(0, 0%, 100%, 0.75)',
'text-halo-width': 1,
'text-halo-blur': 1,
},
interactive: true,
},
]
};

const map = new Map({
container: "map-container", // html container id
// style: "mapbox://styles/mapbox/outdoors-v11", //hosted style id
style: mapStyle,
center: [0, 0], // starting position [经度, 纬度]
zoom: 1, // starting zoom
antialias: true,
// maxZoom: 24,
// minZoom: 1,
// pitch: 0,
// maxPitch: 60,
// // minPitch: 0,
crossSourceCollisions: false,
});

GeoServer 跨域问题

  将 lib 目录中的 jetty-servlets 和 jetty-util 两个 jar 包复制到\webapps\geoserver\WEB-INF\lib目录下,将\webapps\geoserver\WEB-INF\web.xml文件中两个 <!-- Uncomment following filter to enable CORS 注释取消,重启 GeoSever。

后记

  Mapbox 显示的地图可以自定义样式,而且加载速度渲染性能方面也都还可以,最重要的是由于采用前端渲染矢量,所以没有传统瓦片那种缩放模糊的感觉,这点非常好,本来想总结一篇简单的 Mapbox 使用手册,但没时间整理了,还是算了 😅。

参考资料

基于geoserver+mapbox的定制化离线地图技术方案