项目需要展示海外地点标注(且卫星图与标准矢量地图切换),但是高德地图不显示海外地点数据,查了高德的海外LBS
服务,是收费的,而且还处于试运行状态,遇到问题还得提工单,比较麻烦。
后来查了查资料,发现天地图可以满足需求,而且天地图提供给WMTS
服务,高德有个TileLayer
类可以直接调用WTMS
服务。所以便采用使用高德进行点标注等功能,调用天地图的图层方案,完成项目。
实现
// 天地图的访问key
const key = "yourkey";
// 初始化layer
this.staelliteLayers = [
new AMap.TileLayer({
// 天地图矢量地图
getTileUrl: `http://t0.tianditu.gov.cn/DataServer?T=img_w&tk=${key}&x=[x]&y=[y]&l=[z]`,
zIndex: 1,
}),
new AMap.TileLayer({
// 天地图矢量图标记
getTileUrl: `http://t0.tianditu.gov.cn/DataServer?T=cia_w&tk=${key}&x=[x]&y=[y]&l=[z]`,
zIndex: 2,
}),
map.setLayers(this.staelliteLayers);
注:按照天地图官网提供的服务地址,不知道怎么回事会报错,请求失败,最后还是在一边博客上看到了上面的地址写法,才成功。有时候碰到这种问题就很奇怪,无从下手,目前还是没有搞明白官方提供的请求地址应该怎么用,有小伙伴知道在评论里给俺涨涨姿势
getTileUrl
地址按上面的写法是完全可以的,大家需要注意T = cia_w
这个参数,需要什么类型的图层,这个就传什么类型的图层参数,如下图竖框里标出来的,从里面选。
坐标系不一致导致描点偏移问题
(1)天地图:CGCS2000,2000国家大地坐标系;我们其实很多时候直接用WGS84的坐标来代替CGCS2000坐标。因为CGCS2000的定义与WGS84实质一样。采用的参考椭球非常接近。扁率差异引起椭球面上的纬度和高度变化最大达0.1mm。当前测量精度范围内,可以忽略这点差异。可以说两者相容至cm级水平,但若一点的坐标精度达不到cm水平,则不认为CGCS2000和WGS84的坐标是相容的。
(2)百度地图:bd09II坐标。首先了解一下火星坐标,它是在国际标准坐标WGS-84上进行的一次加密,由于国内的电子地图都要至少使用火星坐标进行一次加密,百度直接就任性一些,直接自己又研究了一套加密算法,来了个二次加密,这就是我们所熟知的百度坐标(BD-09)。
(3)高德地图:gcj02坐标,也称为火星坐标。火星坐标是国家测绘局为了国家安全在原始坐标的基础上进行偏移得到的坐标,基本国内的电子地图、导航设备都是采用的这一坐标系或在这一坐标的基础上进行二次加密得到的。
因为高德与天地图使用的坐标系是不一样的,所以在添加点标记之前,要把数据里的高德坐标系下的经纬度转换为天地图坐标系下的。
this.projectsData.forEach((item) => {
// 高德火星地图坐标系转为天地图坐标系
let WGS = transformGCJ2WGS(item.latitude, item.longitude);
item.position = [WGS.lon, WGS.lat];
this.markers.push({
position: item.position,
name: item.name,
label: this.getCurLabel(item.name),
events: {
click: () => {
// this.openInfoWindow(e.target.Ce.position, item);
this.openInfoWindow(item.position, item);
},
},
});
});
具体的转换算法为:
// utils/util.js
var PI = 3.14159265358979324;
/**
* 高德火星地图坐标系转为天地图坐标系
* @param {*} gcjLat 火星坐标经度
* @param {*} gcjLon 火星坐标维度
* @returns
*/
export function transformGCJ2WGS(gcjLat, gcjLon) {
let d = delta(gcjLat, gcjLon)
return {
'lat': gcjLat - d.lat,
'lon': gcjLon - d.lon
}
}
function delta(lat, lon) {
let a = 6378245.0 // a: 卫星椭球坐标投影到平面地图坐标系的投影因子。
let ee = 0.00669342162296594323 // ee: 椭球的偏心率。
let dLat = transformLat(lon - 105.0, lat - 35.0)
let dLon = transformLon(lon - 105.0, lat - 35.0)
let radLat = lat / 180.0 * PI
let magic = Math.sin(radLat)
magic = 1 - ee * magic * magic
let sqrtMagic = Math.sqrt(magic)
dLat = (dLat * 180.0) / ((a * (1 - ee)) / (magic * sqrtMagic) * PI)
dLon = (dLon * 180.0) / (a / sqrtMagic * Math.cos(radLat) * PI)
return {
'lat': dLat,
'lon': dLon
}
}
function transformLat(x, y) {
let ret = -100.0 + 2.0 * x + 3.0 * y + 0.2 * y * y + 0.1 * x * y + 0.2 * Math.sqrt(Math.abs(x))
ret += (20.0 * Math.sin(6.0 * x * PI) + 20.0 * Math.sin(2.0 * x * PI)) * 2.0 / 3.0
ret += (20.0 * Math.sin(y * PI) + 40.0 * Math.sin(y / 3.0 * PI)) * 2.0 / 3.0
ret += (160.0 * Math.sin(y / 12.0 * PI) + 320 * Math.sin(y * PI / 30.0)) * 2.0 / 3.0
return ret
}
function transformLon(x, y) {
let ret = 300.0 + x + 2.0 * y + 0.1 * x * x + 0.1 * x * y + 0.1 * Math.sqrt(Math.abs(x))
ret += (20.0 * Math.sin(6.0 * x * PI) + 20.0 * Math.sin(2.0 * x * PI)) * 2.0 / 3.0
ret += (20.0 * Math.sin(x * PI) + 40.0 * Math.sin(x / 3.0 * PI)) * 2.0 / 3.0
ret += (150.0 * Math.sin(x / 12.0 * PI) + 300.0 * Math.sin(x / 30.0 * PI)) * 2.0 / 3.0
return ret
}
其它类型转换参考:常用的几种在线地图(天地图、百度地图、高德地图)坐标系之间的转换算法