3、坐标系与投影:WGS84、GCJ02、BD09坐标系区别、坐标转换库的使用

做轨迹回放,第一个坑往往不是算法,而是坐标系。

我记得刚入行那会儿,拿到一批GPS数据直接往地图上怼,结果轨迹飘到了河对岸。当时我还以为是设备坏了,折腾了半天才发现——数据是WGS84,地图用的是GCJ02。嗯,坐标没对齐,啥都白搭。

3.1 三大坐标系,到底差在哪儿?

说白了,国内做地图开发,你绕不开这三个坐标系:

坐标系 全称 谁在用 特点
WGS84 World Geodetic System 1984 GPS设备、Google Earth 全球通用,原始卫星数据
GCJ02 国测局坐标 高德、腾讯、Google中国 WGS84加偏移,国内强制使用
BD09 百度坐标 百度地图 GCJ02再加一次偏移,百度独有

你想想看,GPS芯片拿到的原始数据是WGS84,但国内地图厂商出于合规要求,必须用GCJ02。百度更狠,在GCJ02基础上又加密了一层。所以同一个点,三个坐标系能差出几百米。

核心结论:轨迹回放时,数据源和底图必须用同一个坐标系。否则轨迹就是歪的。

3.2 坐标转换,怎么搞?

我在项目中遇到过最头疼的事:客户给了100万条历史轨迹,全是WGS84,但展示平台用的是百度地图。一条条转?不现实。这时候就得靠坐标转换库了。

3.2.1 proj4js —— 专业级投影转换

proj4js是前端GIS的瑞士军刀。它支持各种投影定义,适合做WGS84和GCJ02之间的互转,也能处理UTM、墨卡托等投影。

// 安装
npm install proj4

// 定义投影
const proj4 = require('proj4');

// WGS84 转 GCJ02(需要自定义投影参数)
proj4.defs('GCJ02', '+proj=longlat +ellps=WGS84 +no_defs');

// 转换示例
const [lng, lat] = proj4('WGS84', 'GCJ02', [116.397428, 39.90923]);
console.log(`转换后:${lng}, ${lat}`);

我的习惯:proj4js适合做批量转换,性能稳定。但要注意,它本身不内置GCJ02和BD09的加密算法,需要自己定义偏移参数。

3.2.2 coordtransform —— 国产轻量级方案

如果你只需要在国内坐标系之间互转,coordtransform更直接。它内置了WGS84、GCJ02、BD09的互转算法,开箱即用。

// 安装
npm install coordtransform

// 使用示例
const coordtransform = require('coordtransform');

// WGS84 转 GCJ02
const gcj02 = coordtransform.wgs84togcj02(116.397428, 39.90923);
console.log(`GCJ02:${gcj02[0]}, ${gcj02[1]}`);

// GCJ02 转 BD09
const bd09 = coordtransform.gcj02tobd09(gcj02[0], gcj02[1]);
console.log(`BD09:${bd09[0]}, ${bd09[1]}`);

// 反过来也行
const backToWgs84 = coordtransform.gcj02towgs84(gcj02[0], gcj02[1]);

避坑指南:我曾经在项目里直接用coordtransform转BD09到WGS84,结果发现百度地图的偏移是动态的,不同区域偏移量不一样。后来我改用百度官方提供的坐标转换API,才解决了精度问题。

3.3 坐标系转换的核心逻辑

为了让你更直观地理解,我画了一张图:

坐标系转换流程 WGS84 GPS原始数据 GCJ02 高德/腾讯/Google中国 BD09 百度地图 coordtransform coordtransform 转换说明: • WGS84 → GCJ02:使用 coordtransform.wgs84togcj02() • GCJ02 → BD09:使用 coordtransform.gcj02tobd09() • 反向转换同理,但精度会略有损失(加密算法不可逆) • 虚线箭头表示反向转换,精度不如正向

3.4 实战中的选择建议

我个人习惯这样选:

  • 数据源是WGS84,底图是高德/腾讯 → 用coordtransform转GCJ02,简单直接
  • 数据源是WGS84,底图是百度 → 先转GCJ02,再转BD09,两步走
  • 需要高精度投影转换 → 用proj4js,自定义投影参数
  • 批量处理大量轨迹点 → 建议后端用Python的pyproj或coordTransform_py,前端只做展示

最后提醒一句:坐标转换不是100%精确的。GCJ02和BD09的加密算法是单向的,反向转换会有几十米的误差。如果你的轨迹回放要求厘米级精度,建议直接用WGS84原始数据,配合支持WGS84的底图(比如天地图)。

嗯,坐标系这块儿就聊到这儿。下一节我们聊聊轨迹数据的清洗和预处理——那又是另一个坑了。

可可精品资料库