// 如果底图是中国地图服务(如高德、百度、腾讯地图),则必须先将 WGS84 转为 GCJ-02/BD-09,否则标记会偏移
// 中国地图的瓦片图片是用GCJ-02坐标生成的
// GCJ-02的偏移算法是非线性的,加密算法未公开(不同地区偏移方向和距离不同),无法通过简单平移修正,
// 开源库是通过逆向工程模拟的近似算法,因此使用开源库(如coordtransform等)实现的转换可能存在微小误差
// 国内地图坐标为什么必须加密
// 政策合规:中国法律要求所有公开地图数据必须加密。
// 技术匹配:地图服务商的瓦片和API基于加密坐标构建。
// 用户体验:避免用户看到未加密的真实坐标(国家安全考虑)。
// 核心两类:地理坐标(球面) + 投影坐标(平面) 可以理解为描述位置的两种语言
// 地理坐标 基于椭球体的球面坐标(想象成描述地球仪) 经纬度(λ, φ)度(°)
// 投影坐标 将球面投影到平面的直角坐标 (想象成描述平面地图) (x, y)米(m)
// 引入库
import proj4 from 'proj4';
import { wgs84togcj02, gcj02tobd09, gcj02towgs84 } from 'coordtransform';
// 定义坐标系
proj4.defs([
["EPSG:4326", "+proj=longlat +datum=WGS84 +no_defs"],
["EPSG:3857", "+proj=merc +a=6378137 +b=6378137 +lat_ts=0 +lon_0=0 +x_0=0 +y_0=0 +k=1 +units=m +nadgrids=@null +wktext +no_defs"]
]);
// ===== 1. WGS84 地理坐标转 Web Mercator(EPSG:4326 → EPSG:3857) =====
const wgs84ToWebMercatorResult = {
"type": "MultiPoint",
"coordinates": [
[116.404, 39.915], // 北京
[121.474, 31.230], // 上海
[113.264, 23.129] // 广州
]
};
wgs84ToWebMercatorResult.coordinates = wgs84ToWebMercatorResult.coordinates.map(coord =>
proj4("EPSG:4326", "EPSG:3857", coord)
);
console.log('WGS84地理坐标转Web墨卡托投影坐标', wgs84ToWebMercatorResult);
// ===== 2. Web Mercator 转 WGS84 地理坐标(EPSG:3857 → EPSG:4326) =====
const webMercatorCoords = [12958175, 4855354];
const webMercatorToWgs84Result = proj4("EPSG:3857", "EPSG:4326", webMercatorCoords);
console.log('Web墨卡托投影坐标转WGS84地理坐标', webMercatorToWgs84Result);
// ===== 3. WGS84 转 GCJ-02 火星坐标(国测局GCJ-02) =====
const wgs84Coords = [116.404, 39.915];
const wgs84ToGcj02Result = wgs84togcj02(...wgs84Coords);
console.log('WGS84坐标转国测局GCJ-02坐标', wgs84ToGcj02Result);
// ===== 4. GCJ-02(国测局) 火星坐标转 WGS84 =====
const gcj02Coords = [116.404, 39.915];
const gcj02ToWgs84Result = gcj02towgs84(...gcj02Coords);
console.log('国测局GCJ-02坐标转WGS84坐标', gcj02ToWgs84Result);
// ===== 5. WGS84 转百度 BD-09 =====
const wgs84ToBd09Result = gcj02tobd09(...wgs84togcj02(...wgs84Coords));
console.log('WGS84转百度BD-09', wgs84ToBd09Result);