🐛 运单轨迹与实时定位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 => {
|
export const normalizeCoordinateInput = value => {
|
||||||
const rawValue = String(value ?? '').replace(/[^\d.-]/g, '');
|
const rawValue = String(value ?? '').replace(/[^\d.-]/g, '');
|
||||||
const isNegative = rawValue.startsWith('-');
|
const isNegative = rawValue.startsWith('-');
|
||||||
|
|||||||
@@ -3642,6 +3642,7 @@ import { addressTypeOptions } from '@/option/base/common-address';
|
|||||||
import { packageOptions } from '@/option/business/common';
|
import { packageOptions } from '@/option/business/common';
|
||||||
import { formatUpdateUserName } from '@/utils/audit';
|
import { formatUpdateUserName } from '@/utils/audit';
|
||||||
import { getToken, isAdministrator } from '@/utils/auth';
|
import { getToken, isAdministrator } from '@/utils/auth';
|
||||||
|
import { wgs84ToGcj02 } from '@/utils/coordinate';
|
||||||
import { openImportDialog } from '@/utils/import-excel';
|
import { openImportDialog } from '@/utils/import-excel';
|
||||||
import { normalizeMapSearchResults, searchAmapPlaceText } from '@/utils/map-search';
|
import { normalizeMapSearchResults, searchAmapPlaceText } from '@/utils/map-search';
|
||||||
import { loadMeasurementUnitOptions } from '@/utils/measurement-unit';
|
import { loadMeasurementUnitOptions } from '@/utils/measurement-unit';
|
||||||
@@ -6306,12 +6307,14 @@ export default {
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
async renderWaybillLocateMap(locateInfo) {
|
async renderWaybillLocateMap(locateInfo) {
|
||||||
const longitude = Number(locateInfo?.longitude);
|
const rawLongitude = Number(locateInfo?.longitude);
|
||||||
const latitude = Number(locateInfo?.latitude);
|
const rawLatitude = Number(locateInfo?.latitude);
|
||||||
if (!Number.isFinite(longitude) || !Number.isFinite(latitude)) {
|
if (!Number.isFinite(rawLongitude) || !Number.isFinite(rawLatitude)) {
|
||||||
this.$message.warning('定位坐标无效,无法在地图上展示');
|
this.$message.warning('定位坐标无效,无法在地图上展示');
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
// LBS 返回 WGS-84,高德地图使用 GCJ-02,绘制前需转换
|
||||||
|
const [longitude, latitude] = wgs84ToGcj02(rawLongitude, rawLatitude);
|
||||||
try {
|
try {
|
||||||
await this.loadAmap();
|
await this.loadAmap();
|
||||||
await this.$nextTick();
|
await this.$nextTick();
|
||||||
@@ -6332,7 +6335,7 @@ export default {
|
|||||||
`<div><b>${locateInfo.vehicleNo || '车辆位置'}</b></div>`,
|
`<div><b>${locateInfo.vehicleNo || '车辆位置'}</b></div>`,
|
||||||
locateInfo.locateTime ? `<div>时间:${locateInfo.locateTime}</div>` : '',
|
locateInfo.locateTime ? `<div>时间:${locateInfo.locateTime}</div>` : '',
|
||||||
locateInfo.address ? `<div>地址:${locateInfo.address}</div>` : '',
|
locateInfo.address ? `<div>地址:${locateInfo.address}</div>` : '',
|
||||||
`<div>坐标:${longitude}, ${latitude}</div>`,
|
`<div>坐标:${rawLongitude}, ${rawLatitude}</div>`,
|
||||||
`</div>`,
|
`</div>`,
|
||||||
].join('');
|
].join('');
|
||||||
this.waybillLocateInfoWindow = new window.AMap.InfoWindow({
|
this.waybillLocateInfoWindow = new window.AMap.InfoWindow({
|
||||||
@@ -6359,9 +6362,17 @@ export default {
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
async renderWaybillTrackMap(points) {
|
async renderWaybillTrackMap(points) {
|
||||||
|
// LBS 轨迹为 WGS-84,绘制到高德前转为 GCJ-02
|
||||||
const path = (points || [])
|
const path = (points || [])
|
||||||
.map(item => [Number(item.longitude), Number(item.latitude)])
|
.map(item => {
|
||||||
.filter(item => Number.isFinite(item[0]) && Number.isFinite(item[1]));
|
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) {
|
if (!path.length) {
|
||||||
this.$message.warning('轨迹坐标无效,无法在地图上展示');
|
this.$message.warning('轨迹坐标无效,无法在地图上展示');
|
||||||
return;
|
return;
|
||||||
|
|||||||
Reference in New Issue
Block a user