前言
最近,碰到了需求,想要在高德 sdk 中使用在 geoserver 里面发布的瓦片地图。
还好经过一番研究,在其官方文档中发现,从新版本(v1.4.3开始)的高德 sdk 开始,已经支持加载第三方 wms/wmts 服务了。
为了测试一下是否能用,我们先将官方的示例拷贝过来试一试。
wms 服务
先试试 wms 服务加载:
var wms = new AMap.TileLayer.WMS({
url: "https://ahocevar.com/geoserver/wms",
blend: false,
tileSize: 512,
params: {
LAYERS: "topp:states",
VERSION: "1.3.0",
},
});
wms.setMap(map);
运行起来,你会发现,成功加载了 topp:states 这张矢量地图:
wmts 服务
再试试官方示例的 wmts 服务加载:
var wms = new AMap.TileLayer.WMTS({
url:"https://services.arcgisonline.com/arcgis/rest/services/Demographics/USA_Population_Density/MapServer/WMTS/",
blend: false,
tileSize: 256,
params: { Layer: "0", Version: "1.0.0", Format: "image/png" },
});
wms.setMap(map);
你会发现,也可以成功加载:
但是仔细研究这个示例,你会发现,官方提供的 wmts 服务是加载的 arcgis 提供的瓦片服务。
gwc 方式
我们知道,geoserver 仅提供 gwc 方式来访问 wmts 服务,并且使用 gwc 方式,还能提高瓦片的访问速率。
所以接下来我们研究一下,是否可以在高德 sdk 中,采用 geoserver 提供的 gwc 方式访问 wms 和 wmts 服务。
首先,研究一下 wms 方式,改一下之前的代码:
var wms = new AMap.TileLayer.WMS({
url: "https://ahocevar.com/geoserver/gwc/service/wms", // 改为 gwc 方式
blend: false,
tileSize: 512,
params: {
LAYERS: "topp:states",
VERSION: "1.3.0",
},
});
再次运行,发现并没有成功加载图层,打开控制台,看一下相关请求,可以发现会返回如下错误:
经过一番排查,发现参数里缺少了一个参数 SRS: "EPSG:3857"
,添加上以后,再次尝试:
var wms = new AMap.TileLayer.WMS({
url: "https://ahocevar.com/geoserver/gwc/service/wms",
blend: false,
tileSize: 512,
params: {
LAYERS: "topp:states",
VERSION: "1.3.0",
SRS: "EPSG:3857",
},
});
wms.setMap(map);
发现还是有问题:
瓦片大小对应不上,更改以后,再次尝试:
var wms = new AMap.TileLayer.WMS({
url: "https://ahocevar.com/geoserver/gwc/service/wms",
blend: false,
tileSize: 256,
params: {
LAYERS: "topp:states",
VERSION: "1.3.0",
SRS: "EPSG:3857",
},
});
wms.setMap(map);
发现可以成功加载。
那 wmts 的方式呢?
调整代码如下:
var wms = new AMap.TileLayer.WMTS({
url: "https://ahocevar.com/geoserver/gwc/service/wmts",
blend: false,
tileSize: 256,
params: { Layer: "topp:states", Version: "1.0.0", Format: "image/png" },
});
wms.setMap(map);
再次运行,发现不能正确获取到瓦片,提示如下错误:
发现提示请求的参数不正确,但是高德 sdk 官方文档里明确说了,不要添加 tilematrixset
等参数:
因此可以得出结论,对于 geoserver 的 gwc 方式,高德 sdk 仅支持 wms 服务,不支持 wmts 服务。
结论
如果想要在高德地图中加载 geoserver 发布的瓦片地图服务,得用 wms 的方式,使用方式如下:
var wms = new AMap.TileLayer.WMS({
url: "https://ahocevar.com/geoserver/wms",
blend: false,
tileSize: 512,
params: {
LAYERS: "topp:states",
VERSION: "1.3.0",
},
});
wms.setMap(map);
或者 gwc 方式:
var wms = new AMap.TileLayer.WMS({
url: "https://ahocevar.com/geoserver/gwc/service/wms",
blend: false,
tileSize: 256,
params: {
LAYERS: "topp:states",
VERSION: "1.3.0",
SRS: "EPSG:3857",
},
});
wms.setMap(map);
如果要用 wmts 服务,得用 arcgis 发布的瓦片服务。由于博主也没用过,这里就不过多的涉及了。
如果你非要在高德 sdk 中使用 geoserver 提供的 wmts 服务,也不是没有方法。
你必须得修改 AMap.TileLayer.WMTS
这个类的源码才行,但是由于高德 sdk 并不开源,因此修改起来非常的困难,一般情况下建议直接放弃即可。
其实在高德 sdk 中加载第三方瓦片服务,还存在一个问题,因为高德地图用的是火星坐标系,因此与根据通用的 wgs84 坐标系生成的地图比,会存在偏差。
比如,下面,是我在高德 sdk 中叠加的我在 geoserver 中发布的影像图,我发布的影像图是未经过加密的,坐标系未 ESPG4326。
可以看到,当我选取了江苏常州的奥林匹克体育中心这一块,就会发现瓦片地图中奥林匹克体育中心的位置,与高德地图中的位置偏差了很多。
因此想要同时在高德底图上,叠加标准的第三方瓦片图,看起来并不现实。
虽然高德 sdk 提供了坐标转换的接口,但是我们想要实现纠偏,同样得改源码才能实现。
但是还是同样的问题,高德 sdk 并不开源,想要改源码,着实太困难,并且,对应的接口,也没有提供实现纠偏的参数或者方法。
其实还有一种方式,就是我们发布一张,火星坐标系的影像图。但是这更不可能,因为火星坐标系,由于保密需要,其设置偏移的时候,并不是采用一种公开的算法,而是随机加入偏移,想要保持与高德地图一致,得把我们的图发给高德 sdk 官方的人处理才行。
因此,总结一下,在高德地图 sdk 中加载 geoserver 发布的第三方影像图,确实能加载成功,但是目前不建议使用,除非接下来官方提供了标准地图纠偏相关的方案。