// 如果底圖是中國地圖服務(如高德、百度、騰訊地圖),則必須先將 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);