vuepress-plugin-photomap
Version:
VuePress2插件,用于在文章中插入照片地图组件,类似Apple相册的PhotoMap功能
126 lines (125 loc) • 4.32 kB
JavaScript
import { ref } from 'vue';
export function useExifReader() {
const loading = ref(false);
const error = ref(null);
// 从图片提取EXIF数据
const extractExifData = async (img) => {
try {
// 使用现代的exifr库
const exifr = await import('exifr');
const exifrLib = exifr.default || exifr;
// 从图片中读取GPS和基本EXIF数据
const exifData = await exifrLib.parse(img, {
gps: true,
orientation: true,
tiff: true,
ifd0: true,
exif: true
});
return exifData || {};
}
catch (err) {
console.error('EXIF数据解析失败:', err);
return {};
}
};
// 解析GPS坐标
const parseGPSData = (exifData) => {
// exifr库直接返回十进制度数,不需要转换
const latitude = exifData?.latitude || exifData?.GPSLatitude;
const longitude = exifData?.longitude || exifData?.GPSLongitude;
if (typeof latitude !== 'number' || typeof longitude !== 'number') {
return null;
}
// 验证坐标有效性
if (latitude < -90 || latitude > 90 || longitude < -180 || longitude > 180) {
return null;
}
const gpsData = {
latitude,
longitude
};
// 可选的GPS数据
const altitude = exifData?.altitude || exifData?.GPSAltitude;
if (typeof altitude === 'number') {
gpsData.altitude = altitude;
}
const direction = exifData?.GPSImgDirection;
if (typeof direction === 'number') {
gpsData.direction = direction;
}
return gpsData;
};
// 加载单张图片的EXIF数据
const loadImageExif = async (src, alt = '') => {
return new Promise((resolve) => {
const img = new Image();
img.crossOrigin = 'anonymous';
const photoData = {
src,
alt,
hasGPS: false
};
img.onload = async () => {
try {
// 获取图片尺寸
photoData.width = img.naturalWidth;
photoData.height = img.naturalHeight;
// 提取EXIF数据
const exifData = await extractExifData(img);
// 解析GPS数据
const gpsData = parseGPSData(exifData);
if (gpsData) {
photoData.gps = gpsData;
photoData.hasGPS = true;
}
else {
photoData.error = '该图片不包含GPS位置信息';
}
}
catch (err) {
photoData.error = '解析EXIF数据时出错';
console.warn('EXIF解析错误:', err);
}
resolve(photoData);
};
img.onerror = () => {
photoData.error = '图片加载失败';
resolve(photoData);
};
img.src = src;
});
};
// 批量处理多张图片
const loadImagesExif = async (images) => {
loading.value = true;
error.value = null;
try {
const promises = images.map(img => loadImageExif(img.src, img.alt));
const results = await Promise.all(promises);
// 统计有GPS信息的图片数量
const gpsCount = results.filter(r => r.hasGPS).length;
if (gpsCount === 0) {
error.value = '所有图片都不包含GPS位置信息';
}
else if (gpsCount < images.length) {
console.warn(`${images.length - gpsCount} 张图片缺少GPS信息`);
}
return results;
}
catch (err) {
error.value = '处理图片EXIF数据时出错';
console.error('批量EXIF处理错误:', err);
return [];
}
finally {
loading.value = false;
}
};
return {
loading,
error,
loadImageExif,
loadImagesExif
};
}