分别用js、php实现GS84与GCJ02两种坐标系的互转
高德地图: 使用 GCJ-02 坐标系,也称为火星坐标系。它是基于国际标准 WGS-84 坐标系进行加密处理得到的。
百度地图: 采用 BD-09 坐标系,这是在 GCJ-02 基础上进行二次加密而来的,具有更高的安全性和隐私保护。
天地图: 使用 CGCS2000 坐标系,该坐标系与 WGS-84 存在微小偏差,在要求不高的情况下可以直接与 WGS-84 互换使用。
js
/** * WGS84转GCJ02(火星坐标系) * @param {number} wgsLon WGS84坐标系的经度 * @param {number} wgsLat WGS84坐标系的纬度 * @returns {Array} GCJ02坐标 [经度, 纬度] */ function wgs84ToGcj02(wgsLon, wgsLat) { const PI = 3.14159265358979324; const a = 6378245.0; const ee = 0.00669342162296594323; if (outOfChina(wgsLat, wgsLon)) { return [wgsLon, wgsLat]; } let dLat = transformLat(wgsLon - 105.0, wgsLat - 35.0); let dLon = transformLon(wgsLon - 105.0, wgsLat - 35.0); const radLat = wgsLat / 180.0 * PI; let magic = Math.sin(radLat); magic = 1 - ee * magic * magic; const sqrtMagic = Math.sqrt(magic); dLat = (dLat * 180.0) / ((a * (1 - ee)) / (magic * sqrtMagic) * PI); dLon = (dLon * 180.0) / (a / sqrtMagic * Math.cos(radLat) * PI); const gcjLat = wgsLat + dLat; const gcjLon = wgsLon + dLon; return [gcjLon, gcjLat]; } /** * GCJ02(火星坐标系)转WGS84 * @param {number} gcjLon GCJ02坐标系的经度 * @param {number} gcjLat GCJ02坐标系的纬度 * @returns {Array} WGS84坐标 [经度, 纬度] */ function gcj02ToWgs84(gcjLon, gcjLat) { const PI = 3.14159265358979324; const a = 6378245.0; const ee = 0.00669342162296594323; if (outOfChina(gcjLat, gcjLon)) { return [gcjLon, gcjLat]; } let dLat = transformLat(gcjLon - 105.0, gcjLat - 35.0); let dLon = transformLon(gcjLon - 105.0, gcjLat - 35.0); const radLat = gcjLat / 180.0 * PI; let magic = Math.sin(radLat); magic = 1 - ee * magic * magic; const sqrtMagic = Math.sqrt(magic); dLat = (dLat * 180.0) / ((a * (1 - ee)) / (magic * sqrtMagic) * PI); dLon = (dLon * 180.0) / (a / sqrtMagic * Math.cos(radLat) * PI); const wgsLat = gcjLat - dLat; const wgsLon = gcjLon - dLon; return [wgsLon, wgsLat]; } function transformLat(x, y) { let ret = -100.0 + 2.0 * x + 3.0 * y + 0.2 * y * y + 0.1 * x * y + 0.2 * Math.sqrt(Math.abs(x)); ret += (20.0 * Math.sin(6.0 * x * Math.PI) + 20.0 * Math.sin(2.0 * x * Math.PI)) * 2.0 / 3.0; ret += (20.0 * Math.sin(y * Math.PI) + 40.0 * Math.sin(y / 3.0 * Math.PI)) * 2.0 / 3.0; ret += (160.0 * Math.sin(y / 12.0 * Math.PI) + 320 * Math.sin(y * Math.PI / 30.0)) * 2.0 / 3.0; return ret; } function transformLon(x, y) { let ret = 300.0 + x + 2.0 * y + 0.1 * x * x + 0.1 * x * y + 0.1 * Math.sqrt(Math.abs(x)); ret += (20.0 * Math.sin(6.0 * x * Math.PI) + 20.0 * Math.sin(2.0 * x * Math.PI)) * 2.0 / 3.0; ret += (20.0 * Math.sin(x * Math.PI) + 40.0 * Math.sin(x / 3.0 * Math.PI)) * 2.0 / 3.0; ret += (150.0 * Math.sin(x / 12.0 * Math.PI) + 300.0 * Math.sin(x / 30.0 * Math.PI)) * 2.0 / 3.0; return ret; } function outOfChina(lat, lon) { return lon < 72.004 || lon > 137.8347 || lat < 0.8293 || lat > 55.8271; } // 使用示例 // let gcjCoord = wgs84ToGcj02(116.404, 39.915); // WGS84转GCJ02 // let wgsCoord = gcj02ToWgs84(116.404, 39.915); // GCJ02转WGS84
PHP
/** * WGS84转GCJ02(火星坐标系) * @param float $wgsLon WGS84坐标系的经度 * @param float $wgsLat WGS84坐标系的纬度 * @return array GCJ02坐标 [经度, 纬度] */ function wgs84ToGcj02($wgsLon, $wgsLat) { $PI = 3.14159265358979324; $a = 6378245.0; $ee = 0.00669342162296594323; if (outOfChina($wgsLat, $wgsLon)) { return array($wgsLon, $wgsLat); } $dLat = transformLat($wgsLon - 105.0, $wgsLat - 35.0); $dLon = transformLon($wgsLon - 105.0, $wgsLat - 35.0); $radLat = $wgsLat / 180.0 * $PI; $magic = sin($radLat); $magic = 1 - $ee * $magic * $magic; $sqrtMagic = sqrt($magic); $dLat = ($dLat * 180.0) / (($a * (1 - $ee)) / ($magic * $sqrtMagic) * $PI); $dLon = ($dLon * 180.0) / ($a / $sqrtMagic * cos($radLat) * $PI); $gcjLat = $wgsLat + $dLat; $gcjLon = $wgsLon + $dLon; return array($gcjLon, $gcjLat); } /** * GCJ02(火星坐标系)转WGS84 * @param float $gcjLon GCJ02坐标系的经度 * @param float $gcjLat GCJ02坐标系的纬度 * @return array WGS84坐标 [经度, 纬度] */ function gcj02ToWgs84($gcjLon, $gcjLat) { $PI = 3.14159265358979324; $a = 6378245.0; $ee = 0.00669342162296594323; if (outOfChina($gcjLat, $gcjLon)) { return array($gcjLon, $gcjLat); } $dLat = transformLat($gcjLon - 105.0, $gcjLat - 35.0); $dLon = transformLon($gcjLon - 105.0, $gcjLat - 35.0); $radLat = $gcjLat / 180.0 * $PI; $magic = sin($radLat); $magic = 1 - $ee * $magic * $magic; $sqrtMagic = sqrt($magic); $dLat = ($dLat * 180.0) / (($a * (1 - $ee)) / ($magic * $sqrtMagic) * $PI); $dLon = ($dLon * 180.0) / ($a / $sqrtMagic * cos($radLat) * $PI); $wgsLat = $gcjLat - $dLat; $wgsLon = $gcjLon - $dLon; return array($wgsLon, $wgsLat); } function transformLat($x, $y) { $ret = -100.0 + 2.0 * $x + 3.0 * $y + 0.2 * $y * $y + 0.1 * $x * $y + 0.2 * sqrt(abs($x)); $ret += (20.0 * sin(6.0 * $x * M_PI) + 20.0 * sin(2.0 * $x * M_PI)) * 2.0 / 3.0; $ret += (20.0 * sin($y * M_PI) + 40.0 * sin($y / 3.0 * M_PI)) * 2.0 / 3.0; $ret += (160.0 * sin($y / 12.0 * M_PI) + 320 * sin($y * M_PI / 30.0)) * 2.0 / 3.0; return $ret; } function transformLon($x, $y) { $ret = 300.0 + $x + 2.0 * $y + 0.1 * $x * $x + 0.1 * $x * $y + 0.1 * sqrt(abs($x)); $ret += (20.0 * sin(6.0 * $x * M_PI) + 20.0 * sin(2.0 * $x * M_PI)) * 2.0 / 3.0; $ret += (20.0 * sin($x * M_PI) + 40.0 * sin($x / 3.0 * M_PI)) * 2.0 / 3.0; $ret += (150.0 * sin($x / 12.0 * M_PI) + 300.0 * sin($x / 30.0 * M_PI)) * 2.0 / 3.0; return $ret; } function outOfChina($lat, $lon) { return $lon < 72.004 || $lon > 137.8347 || $lat < 0.8293 || $lat > 55.8271; } // 使用示例 // $gcjCoord = wgs84ToGcj02(116.404, 39.915); // WGS84转GCJ02 // $wgsCoord = gcj02ToWgs84(116.404, 39.915); // GCJ02转WGS84