🐛 运单轨迹与实时定位WGS-84转GCJ-02后再绘制高德地图
Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
@@ -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;
|
||||
|
||||
Reference in New Issue
Block a user