高德地图坐标系是火星坐标系,而天地图是84坐标系,两种不同的坐标系地图是无法直接使用切片加载的方式共同使用的。已实现的地图相关功能都是高德地图引擎进行开发的,怎样引入天地图,同时又可以直接使用已有的地图功能成为了设计难题。
初始设计方案是引入天地图引擎,进行天地图切片的加载。对于基于高德引擎提供的JSAPI实现的地图相关功能,使用天地图引擎提供的API重新实现一遍即可。但是此方案的成本有点高,开发周期不可控,而且以后地图新增功能点时都要使用这两种地图引擎分别实现功能点,维护成本高。
后经研究发现使用高德引擎可以直接加载天地图切片,但是加载的天地图切片有一定的偏移量。使用地理坐标系转换开源库可解决此问题。
1.加载天地图切片
使用高德地图引擎加载天地图切片有两种实现方式,第一种是天地图官网提供的加载wmts图层切片的形式,第二种是网上查到的以前的天地图切片加载方式;不知道这两种加载天地图切片有什么区别,经试验都能正常加载天地图切片,核心代码如下:
// 方式一:加载天地图影像切片
new AMap.TileLayer.WMTS({
url: 'http://t0.tianditu.gov.cn/img_w/wmts',
blend: false,
tileSize: 256,
zIndex: 80,
params: { // 参数必须按照天地图官网规范来,不要相信高德官网
// ......
},
});
// 方式二:加载天地图影像切片
new window.AMap.TileLayer({
zIndex: 2,
getTileUrl(x, y, z) {
return `https://t0.tianditu.gov.cn/DataServerT=img_w&x=${x}&y=${y}&l=${z}&tk=....`;
},
});
加载完成天地图切片后会发现切片有一定的偏移,在相同可视区内展示的地图切片完全不同。加载高德卫星影像切片时是正常加载,而当切换为加载天地图卫星影像切片时,此时地图的中心点与地图可视区范围的四个角的经纬度都是火星坐标经纬度,拿火星坐标经纬度去请求84坐标系的天地图切片,获取到的天地图切片肯定不是可视区内应该需要展示的切片,导致了加载的天地图的切片有一定偏移量的现象。
解决方法是在切换为加载天地图卫星影像切片时,先获取到地图的中心点火星坐标经纬度,将地图的中心点经纬度转为84经纬度,再将转换后的84经纬度设置为此时地图的中心点即可。这样地图可视区范围的四个角也都是84坐标经纬度,从而加载的天地图切片是可视区内需要展示的切片。
同理,在加载并展示天地图切片后,当想切换为加载高德切片展示时,转换方式与上述方法一样,只不过要将地图中心点当作84经纬度,转为火星经纬度。相关核心代码如下:
基于
gcoord
库封封装的经纬度坐标系转换
:
import gcoord from 'gcoord';
// GCJ02坐标转WGS84坐标
GCJ02ToWGS84(arr) {
const temp = gcoord.transform(arr, gcoord.GCJ02, gcoord.WGS84);
return {
Q: temp[1],
R: temp[0],
lat: temp[1],
lng: temp[0],
};
},
// WGS84坐标转GCJ02坐标
WGS84ToGCJ02(arr) {
const temp = gcoord.transform(arr, gcoord.WGS84, gcoord.GCJ02);
return {
Q: temp[1],
R: temp[0],
lat: temp[1],
lng: temp[0],
};
},
高德图层与天地图图层切换
:
......
const center = window.map.getCenter();
if (val.startsWith('tian')) {
center = this.GCJ02ToWGS84([center.R, center.Q]);
} else {
center = this.WGS84ToGCJ02([center.R, center.Q]);
}
window.map.setCenter(center);
在相同的可视区,使用此方法加载的高德卫星影像切片与天地图卫星影像切片完全相同,解决了高德引擎加载天地图切片出现切片偏移的现象。
2.兼容地图功能
加载完成天地图切片后,地图上已实现的功能点在天地图切片展示时也需正常使用,即兼容地图功能。
下面以地图上的新建点位这个功能点为例, 在加载天地图切片时如何兼容此功能点。
在加载天地图切片后,在地图上新建点位时,所获取到的鼠标所点击位置的经纬度信息是火星坐标经纬度,如果直接拿所获取到的经纬度调取高德引擎提供的
geocoder
插件来获取此经纬度所对应的地理位置信息是不正确的。
处理方法是将所获取到的鼠标所点击位置的经纬度当作84坐标经纬度,然后将此经纬度转为火星坐标经纬度后,再调取高德引擎提供的
geocoder
插件来获取此经纬度所对应的地理位置信息,处理后进行新建点位得到的是正确的地理位置信息。核心代码如下:
addPoint(e) {
let lnglatPs;
if (this.isFire) { // 加载高德切片
lnglatPs = { Q: e.lnglat.Q, R: e.lnglat.R };
} else { // 加载天地图切片
lnglatPs = this.WGS84ToGCJ02([e.lnglat.R, e.lnglat.Q]);
}
this.geocoder.getAddress([lnglatPs.R, lnglatPs.Q], (status, result) => {
if (status === 'complete' && result.info === 'OK') {
// .......
}
});
},
其他的地图功能点都以此为例进行兼容处理即可。