凌晨两点,值班群弹出一条:“线上地图所有 POI 都偏了,大概几百米,全上海的点都往一个方向挪。”
第一反应是瓦片服务挂了。查了一圈,地图正常、接口正常、数据正常——直到发现新导入的一批 POI 是 GPS 设备直出的 WGS84 坐标,直接喂给了 GCJ-02 的地图。
几百米不是偏差,是坐标系没转。这篇把三坐标系互转的代码、适用场景和排查方法一次讲清。结论先说:采集层统一转 GCJ-02 入库,展示层不再转;WGS84↔GCJ-02 没有官方公开算法,网上实现是近似解,涉及计费/围栏/考勤必须走官方转换接口。
💰 商用授权成本自测:坐标转换接口(ws/coord/v1/translate)免费额度只用于测试,商用无论调用量多少都要办商业授权(基础版 5 万/年)。文末有免费测算入口。
一、事故现场:三个坐标系是怎么来的
国内地图有三层坐标系,关系是层层加密:
- WGS84:GPS 卫星原始坐标,设备直出。硬件(手机、定位器、车载终端)拿到的都是它。
- GCJ-02(火星坐标):国测局对 WGS84 做非线性偏移,国内绝大多数互联网地图的基础坐标系——腾讯、高德都用它。
- BD-09:百度在 GCJ-02 基础上再次加密,国内(含港澳台)默认用它,海外才用 WGS84。
事故的根源:数据源(WGS84)、地图底图(GCJ-02 或 BD-09)、你调的服务 API——三者坐标系一旦混用,偏差就是百米级、肉眼可见,还会一路污染到围栏判定和轨迹里程。
二、修复代码:三段可复用的转换函数
先给能直接用的。GCJ-02 ↔ BD-09 的互转公式是业界通用实现(百度文档同款逻辑);WGS84 ↔ GCJ-02 没有官方公开算法,以下为社区通行近似实现,标注清楚适用范围:
const X_PI = Math.PI * 3000.0 / 180.0
// GCJ-02 → BD-09(百度地图坐标系)
function gcj02ToBd09(lng, lat) {
const z = Math.sqrt(lng * lng + lat * lat) + 0.00002 * Math.sin(lat * X_PI)
const t = Math.atan2(lat, lng) + 0.000003 * Math.cos(lng * X_PI)
return [z * Math.cos(t) + 0.0065, z * Math.sin(t) + 0.006]
}
// BD-09 → GCJ-02(从百度回到通用坐标系)
function bd09ToGcj02(lng, lat) {
const x = lng – 0.0065, y = lat – 0.006
const z = Math.sqrt(x * x + y * y) – 0.00002 * Math.sin(y * X_PI)
const t = Math.atan2(y, x) – 0.000003 * Math.cos(x * X_PI)
return [z * Math.cos(t), z * Math.sin(t)]
}
// WGS84 → GCJ-02(GPS 坐标上图前必转)
// 注意:此为社区近似实现,非官方算法,展示用可以,计费/围栏/考勤别用
function wgs84ToGcj02(lng, lat) {
// …(较长,社区实现,按精度要求选用)
// 有责任边界的场景,请改用腾讯位置服务官方转换接口
// GET https://apis.map.qq.com/ws/coord/v1/translate
}
两个必懂的点:
三、继续排查:事故里还有哪些隐蔽坑
坑一:百度同厂两个 SDK 坐标系不一致。 百度官方 FAQ 白纸黑字:地图 SDK 国内默认 BD09,而定位 SDK 默认输出 GCJ02。你以为"都是百度不会错",实际定位点喂给地图就偏。这也是"没换供应商却偏了"的隐蔽来源。
坑二:ws/coord/v1/translate 是单向的。 官方描述是"从其它坐标系转换到腾讯地图坐标系"——GCJ-02 转回 WGS84 没有官方接口。网上 gcj02towgs84() 全是拟合近似解,做司法举证、计费复核这类场景不能用来做结论。
坑三:转换函数传参顺序。 locations 参数纬度在前、经度在后,跟大多数人习惯相反。写反了某些区域不报错,只是给你一个几百公里外的坐标——比偏移更难排查。
四、预防:一套坐标系贯穿到底
上线后这次事故的修复方案,其实就一句话:规定数据流里只有一个坐标系。
- 采集层:设备 WGS84,服务端入口统一转 GCJ-02
- 存储层:全库 GCJ-02,字段名带 _gcj02 后缀,杜绝歧义
- 展示层:腾讯/高德直接渲染 GCJ-02,百度场景才在出口转 BD-09
- 有责任边界的场景(计费里程、考勤围栏、司法举证):保留原始 WGS84 字段做底稿,转换结果只用于计算和展示
相关阅读:本系列《地图 API 选型对比》讲了坐标系选型为什么决定接入成本;《轨迹纠偏四开关对照》讲轨迹坐标的处理;坐标转换接口的单向性在《坐标系转换方向性》里展开过。
帮你把坐标系账算清楚
坐标转换这种接口,授权费(基础版 5 万/年)是固定成本、跟调用量无关;真正能省的是流量包——同一点反复转换毫无意义,按坐标截断 4 位(≈11 米)做缓存键,同栋楼的转换结果直接命中缓存,能省下一大截调用。
你的数据源是什么(GPS 设备 / 小程序 / 存量 BD-09)?出口在哪(腾讯 / 高德 / 百度)?把这两个坐标信息丢评论区,或填成本测算表(6 项,2 分钟),我按官方档位帮你算授权版本 + 流量包预估,包括转换链路怎么设计最省。免费,1 个工作日内回。





