高德地图官方转坐标失败
最近开发自己结婚要用的网站,里面用到了高德地图,之前开发过类似的地图功能,所以信誓旦旦很快能搞定,但是在用高德 JS API 2.0 的官方定位插件进行定位时,发现有个问题,无论如何都会出现位置偏移。
之前开发过,我知道各家坐标系的问题,但是我这是高德自己定位自己用,没有第三方的坐标来源,怎么会出现偏移?
特别是我在配置插件的时候已经设置了转换为 true, 在开发环境就能定位准确,在部署生产后就一直有偏移。
ts
useEffect(() => {
// 确保代码只在客户端执行
if (typeof window === "undefined") return;
if (!mapRef.current) return;
// 确保只初始化一次地图
if (map) return;
let mapInstance: AMap.Map | null = null;
// 设置安全密钥(如果有的话)
if (process.env.NEXT_PUBLIC_AMAP_SECURITY_KEY) {
(
window as typeof window & {
_AMapSecurityConfig?: { securityJsCode: string };
}
)._AMapSecurityConfig = {
securityJsCode: process.env.NEXT_PUBLIC_AMAP_SECURITY_KEY,
};
} else {
console.warn("SECURITY_KEY 加载失败");
}
// 动态加载高德地图
const loadAMap = async () => {
const AMapLoader = (await import("@amap/amap-jsapi-loader")).default;
return AMapLoader.load({
key: process.env.NEXT_PUBLIC_AMAP_KEY || "", // 使用环境变量中的API密钥
version: "2.0",
plugins: ["AMap.Scale", "AMap.ToolBar", "AMap.Geolocation"],
});
};
loadAMap()
.then((AMap) => {
// 保存AMap对象以便后续使用
setAMapInstance(AMap);
// 创建地图实例
const instance = new AMap.Map(mapRef.current, {
zoom: 15,
center: [111.1111, 222.2222], // 初始中心点,需要替换为实际坐标
resizeEnable: true,
});
mapInstance = instance;
// 添加比例尺控件
instance.addControl(new AMap.Scale());
// 添加工具条控件
const toolbar = new AMap.ToolBar({
position: "RT", // 设置工具栏在右上角
});
instance.addControl(toolbar);
// 添加定位控件
const geolocation = new AMap.Geolocation({
enableHighAccuracy: true,
timeout: 15000, // 增加超时时间
maximumAge: 0, // 不使用浏览器原生定位的缓存时间,毫秒
convert: true, // 是否将定位结果转换为高德坐标
position: "RT", // 右上角
offset: [15, 85], // 缩略图距离悬停位置的像素距离
panToLocation: true, // 定位成功后是否自动移动到响应位置
zoomToAccuracy: true, // 定位成功后是否自动调整级别
});
// 添加定位回调
geolocation.on("complete", (data: AMap.Geolocation.GeolocationResult) => {
console.log("定位成功", data);
});
geolocation.on("error", (error: AMap.Geolocation.ErrorStatus) => {
console.error("定位失败", error);
});
instance.addControl(geolocation);
setMap(instance);
})
.catch((e) => {
console.error("地图加载失败", e);
});
// 清理函数
return () => {
if (mapInstance) {
mapInstance.destroy();
}
};
}, []); // 只在组件挂载时初始化一次于是尝试抓包,发现定位的结果如下:
js
// 打印: 定位成功
{
status: 0,
code: 0,
info: "SUCCESS",
position: [111.1111, 222.222], // 这是脱敏的位置数据
location_type: html5,
message: "Get geolocation success.Convert failed.", // 这里提示转换失败
accuracy: 75,
isConverted: false,
altitude: null,
altitudeAccuracy: null,
heading: null,
speed: null,
type: "complete"
}message:Get geolocation success.Convert failed.
这句话很可疑,因为我在配置插件的时候已经设置了转换为 true。
于是去提交了工单,高德的工程师反馈,这个转换错误,大概率是因为安全密钥没有挂载成功,往这个方向排查。结果我去看,生产果然没有配置这个变量,开发环境配置了所以能够精准定位。
于是赶紧去生产配置,重新部署,搞定。
补充知识 1: 高德地图的坐标转换 在中国,地图坐标系统比较特殊。主要有以下几种坐标系:
- WGS84 坐标系:国际标准坐标系,GPS 设备获取的原始坐标。
- GCJ-02 坐标系:国测局 02 年发布的坐标系统,也叫火星坐标系,是在 WGS84 基础上加密偏移后的坐标系。高德地图、腾讯地图、Google 中国地图使用此坐标系。
- BD-09 坐标系:百度坐标系,在 GCJ-02 基础上再次加密偏移后的坐标系。
高德地图的坐标转换主要涉及以下几种情况:
- HTML5 Geolocation API 获取的坐标:这是 WGS84 坐标系,需要转换为 GCJ-02 才能在高德地图上准确显示。
- 第三方设备获取的 GPS 坐标:同样是 WGS84 坐标系,需要转换。
- 其他地图平台的坐标:如百度地图的 BD-09 坐标,需要先转换为 GCJ-02。
在高德地图 API 中,
convert参数就是控制是否进行这种转换的关键。当设置convert: true时,API 会尝试将获取到的坐标转换为高德的 GCJ-02 坐标系。但这个转换需要安全密钥(Security Key)正确配置才能生效,否则会出现"Convert failed"的错误。如果需要手动进行坐标转换,高德地图提供了坐标转换服务 API:
https://restapi.amap.com/v3/assistant/coordinate/convert此外,也有一些开源的坐标转换工具库可以在前端直接使用,如 coordtransform、gcoord 等。
补充知识 2:Convert failed
高德的工程师反馈,这个报错基本就是因为安全密钥未配置或者配置错误导致的,如果看到这个报错,请着重往这个方向排查。
