🐛 运单轨迹与实时定位WGS-84转GCJ-02后再绘制高德地图

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
2026-10-08 19:37:27 +08:00
parent d1f804056e
commit 570fbeb537
2 changed files with 103 additions and 6 deletions
+86
View File
@@ -13,6 +13,92 @@ const coordinateRanges = {
},
};
/** WGS-84 → GCJ-02(高德)偏移算法常量 */
const WGS84_TO_GCJ02_PI = Math.PI;
const WGS84_TO_GCJ02_A = 6378245.0;
const WGS84_TO_GCJ02_EE = 0.00669342162296594323;
const isOutOfChina = (longitude, latitude) =>
longitude < 72.004 || longitude > 137.8347 || latitude < 0.8293 || latitude > 55.8271;
const transformLatitude = (longitude, latitude) => {
let result =
-100.0 +
2.0 * longitude +
3.0 * latitude +
0.2 * latitude * latitude +
0.1 * longitude * latitude +
0.2 * Math.sqrt(Math.abs(longitude));
result +=
((20.0 * Math.sin(6.0 * longitude * WGS84_TO_GCJ02_PI) +
20.0 * Math.sin(2.0 * longitude * WGS84_TO_GCJ02_PI)) *
2.0) /
3.0;
result +=
((20.0 * Math.sin(latitude * WGS84_TO_GCJ02_PI) +
40.0 * Math.sin((latitude / 3.0) * WGS84_TO_GCJ02_PI)) *
2.0) /
3.0;
result +=
((160.0 * Math.sin((latitude / 12.0) * WGS84_TO_GCJ02_PI) +
320 * Math.sin((latitude * WGS84_TO_GCJ02_PI) / 30.0)) *
2.0) /
3.0;
return result;
};
const transformLongitude = (longitude, latitude) => {
let result =
300.0 +
longitude +
2.0 * latitude +
0.1 * longitude * longitude +
0.1 * longitude * latitude +
0.1 * Math.sqrt(Math.abs(longitude));
result +=
((20.0 * Math.sin(6.0 * longitude * WGS84_TO_GCJ02_PI) +
20.0 * Math.sin(2.0 * longitude * WGS84_TO_GCJ02_PI)) *
2.0) /
3.0;
result +=
((20.0 * Math.sin(longitude * WGS84_TO_GCJ02_PI) +
40.0 * Math.sin((longitude / 3.0) * WGS84_TO_GCJ02_PI)) *
2.0) /
3.0;
result +=
((150.0 * Math.sin((longitude / 12.0) * WGS84_TO_GCJ02_PI) +
300.0 * Math.sin((longitude / 30.0) * WGS84_TO_GCJ02_PI)) *
2.0) /
3.0;
return result;
};
/**
* WGS-84(GPS / LBS)转 GCJ-02(高德/国测局),供高德地图绘制使用。
* 中国境外坐标不做偏移,原样返回。
* @param {number} longitude
* @param {number} latitude
* @returns {[number, number]} [经度, 纬度]
*/
export const wgs84ToGcj02 = (longitude, latitude) => {
const lng = Number(longitude);
const lat = Number(latitude);
if (!Number.isFinite(lng) || !Number.isFinite(lat) || isOutOfChina(lng, lat)) {
return [lng, lat];
}
let dLat = transformLatitude(lng - 105.0, lat - 35.0);
let dLng = transformLongitude(lng - 105.0, lat - 35.0);
const radLat = (lat / 180.0) * WGS84_TO_GCJ02_PI;
let magic = Math.sin(radLat);
magic = 1 - WGS84_TO_GCJ02_EE * magic * magic;
const sqrtMagic = Math.sqrt(magic);
dLat =
(dLat * 180.0) /
(((WGS84_TO_GCJ02_A * (1 - WGS84_TO_GCJ02_EE)) / (magic * sqrtMagic)) * WGS84_TO_GCJ02_PI);
dLng = (dLng * 180.0) / ((WGS84_TO_GCJ02_A / sqrtMagic) * Math.cos(radLat) * WGS84_TO_GCJ02_PI);
return [lng + dLng, lat + dLat];
};
export const normalizeCoordinateInput = value => {
const rawValue = String(value ?? '').replace(/[^\d.-]/g, '');
const isNegative = rawValue.startsWith('-');
@@ -3642,6 +3642,7 @@ import { addressTypeOptions } from '@/option/base/common-address';
import { packageOptions } from '@/option/business/common';
import { formatUpdateUserName } from '@/utils/audit';
import { getToken, isAdministrator } from '@/utils/auth';
import { wgs84ToGcj02 } from '@/utils/coordinate';
import { openImportDialog } from '@/utils/import-excel';
import { normalizeMapSearchResults, searchAmapPlaceText } from '@/utils/map-search';
import { loadMeasurementUnitOptions } from '@/utils/measurement-unit';
@@ -6306,12 +6307,14 @@ export default {
}
},
async renderWaybillLocateMap(locateInfo) {
const longitude = Number(locateInfo?.longitude);
const latitude = Number(locateInfo?.latitude);
if (!Number.isFinite(longitude) || !Number.isFinite(latitude)) {
const rawLongitude = Number(locateInfo?.longitude);
const rawLatitude = Number(locateInfo?.latitude);
if (!Number.isFinite(rawLongitude) || !Number.isFinite(rawLatitude)) {
this.$message.warning('定位坐标无效,无法在地图上展示');
return;
}
// LBS 返回 WGS-84,高德地图使用 GCJ-02,绘制前需转换
const [longitude, latitude] = wgs84ToGcj02(rawLongitude, rawLatitude);
try {
await this.loadAmap();
await this.$nextTick();
@@ -6332,7 +6335,7 @@ export default {
`<div><b>${locateInfo.vehicleNo || '车辆位置'}</b></div>`,
locateInfo.locateTime ? `<div>时间:${locateInfo.locateTime}</div>` : '',
locateInfo.address ? `<div>地址:${locateInfo.address}</div>` : '',
`<div>坐标:${longitude}, ${latitude}</div>`,
`<div>坐标:${rawLongitude}, ${rawLatitude}</div>`,
`</div>`,
].join('');
this.waybillLocateInfoWindow = new window.AMap.InfoWindow({
@@ -6359,9 +6362,17 @@ export default {
}
},
async renderWaybillTrackMap(points) {
// LBS 轨迹为 WGS-84,绘制到高德前转为 GCJ-02
const path = (points || [])
.map(item => [Number(item.longitude), Number(item.latitude)])
.filter(item => Number.isFinite(item[0]) && Number.isFinite(item[1]));
.map(item => {
const longitude = Number(item.longitude);
const latitude = Number(item.latitude);
if (!Number.isFinite(longitude) || !Number.isFinite(latitude)) {
return null;
}
return wgs84ToGcj02(longitude, latitude);
})
.filter(Boolean);
if (!path.length) {
this.$message.warning('轨迹坐标无效,无法在地图上展示');
return;