vuepress-plugin-photomap
Version:
VuePress2插件,用于在文章中插入照片地图组件,类似Apple相册的PhotoMap功能
134 lines (133 loc) • 4.23 kB
JavaScript
/**
* 坐标转换工具函数
*/
/**
* 度分秒(DMS)转十进制度(DD)
*/
export const dmsToDecimal = (dms, direction) => {
if (!dms || dms.length < 3) {
throw new Error('Invalid DMS format');
}
const [degrees, minutes, seconds] = dms;
let decimal = degrees + minutes / 60 + seconds / 3600;
// 南纬和西经为负值
if (direction === 'S' || direction === 'W') {
decimal = -decimal;
}
return decimal;
};
/**
* 十进制度(DD)转度分秒(DMS)
*/
export const decimalToDMS = (decimal, isLatitude = true) => {
const absDecimal = Math.abs(decimal);
const degrees = Math.floor(absDecimal);
const minutesFloat = (absDecimal - degrees) * 60;
const minutes = Math.floor(minutesFloat);
const seconds = (minutesFloat - minutes) * 60;
let direction;
if (isLatitude) {
direction = decimal >= 0 ? 'N' : 'S';
}
else {
direction = decimal >= 0 ? 'E' : 'W';
}
return {
degrees,
minutes,
seconds: Math.round(seconds * 1000) / 1000, // 保留3位小数
direction
};
};
/**
* 验证经纬度坐标是否有效
*/
export const validateCoordinates = (lat, lng) => {
return (typeof lat === 'number' &&
typeof lng === 'number' &&
!isNaN(lat) &&
!isNaN(lng) &&
lat >= -90 &&
lat <= 90 &&
lng >= -180 &&
lng <= 180);
};
/**
* 计算两点之间的距离(使用Haversine公式)
* @param coord1 起点坐标
* @param coord2 终点坐标
* @returns 距离(单位:米)
*/
export const calculateDistance = (coord1, coord2) => {
const R = 6371000; // 地球半径(米)
const φ1 = (coord1.latitude * Math.PI) / 180;
const φ2 = (coord2.latitude * Math.PI) / 180;
const Δφ = ((coord2.latitude - coord1.latitude) * Math.PI) / 180;
const Δλ = ((coord2.longitude - coord1.longitude) * Math.PI) / 180;
const a = Math.sin(Δφ / 2) * Math.sin(Δφ / 2) +
Math.cos(φ1) * Math.cos(φ2) * Math.sin(Δλ / 2) * Math.sin(Δλ / 2);
const c = 2 * Math.atan2(Math.sqrt(a), Math.sqrt(1 - a));
return R * c;
};
/**
* 计算地理边界框
*/
export const calculateBounds = (coordinates) => {
if (coordinates.length === 0) {
throw new Error('No coordinates provided');
}
let north = coordinates[0].latitude;
let south = coordinates[0].latitude;
let east = coordinates[0].longitude;
let west = coordinates[0].longitude;
coordinates.forEach(coord => {
north = Math.max(north, coord.latitude);
south = Math.min(south, coord.latitude);
east = Math.max(east, coord.longitude);
west = Math.min(west, coord.longitude);
});
return { north, south, east, west };
};
/**
* 计算地理中心点
*/
export const calculateCenter = (coordinates) => {
if (coordinates.length === 0) {
throw new Error('No coordinates provided');
}
if (coordinates.length === 1) {
return coordinates[0];
}
let x = 0;
let y = 0;
let z = 0;
coordinates.forEach(coord => {
const lat = (coord.latitude * Math.PI) / 180;
const lng = (coord.longitude * Math.PI) / 180;
x += Math.cos(lat) * Math.cos(lng);
y += Math.cos(lat) * Math.sin(lng);
z += Math.sin(lat);
});
const total = coordinates.length;
x /= total;
y /= total;
z /= total;
const centralLongitude = Math.atan2(y, x);
const centralSquareRoot = Math.sqrt(x * x + y * y);
const centralLatitude = Math.atan2(z, centralSquareRoot);
return {
latitude: (centralLatitude * 180) / Math.PI,
longitude: (centralLongitude * 180) / Math.PI
};
};
/**
* 格式化坐标显示
*/
export const formatCoordinate = (coord, format = 'decimal') => {
if (format === 'dms') {
const latDMS = decimalToDMS(coord.latitude, true);
const lngDMS = decimalToDMS(coord.longitude, false);
return `${latDMS.degrees}°${latDMS.minutes}'${latDMS.seconds.toFixed(1)}"${latDMS.direction} ${lngDMS.degrees}°${lngDMS.minutes}'${lngDMS.seconds.toFixed(1)}"${lngDMS.direction}`;
}
return `${coord.latitude.toFixed(6)}, ${coord.longitude.toFixed(6)}`;
};