前言
最近做项目需要用到 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 设置新的坐标系统。
地图发布
在 数据 栏下:
- 点击工作区,添加新的工作区,命名以及填写 URI,勾选默认工作区。
- 点击数据存储,添加新的数据存储,选择数据源,以 Directory of spatial files (shapefiles) 为例,在连接参数下点击 浏览,选择shape文件存放目录,DBF 文件字符集选择 UTF-8 或 GBK。注: shape 文件名中不能有中文。
- 点击图层,添加新的资源,添加图层,选择上一步的添加的数据存储名称,点击发布或再次发布,进入发布配置界面,勾选 广告则会在 Layer Preview 中显示,一般不需要勾选,点击
Compute from native bounds
,GeoServer 会自动计算边框和经纬度信息,然后勾选Linear geometries can contain cicular arcs
,使线性几何图形包含环形弧,然后保存。重复当前步骤,直到数据存储中所有图层都发布完毕。 - 点击图层组,添加新的图层组,添加图层,然后点击 生成边界,保存,即完成整个地图的发布。
在 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 | const mapStyle: mapboxgl.Style = { |
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 使用手册,但没时间整理了,还是算了 😅。