/** * 地图配置文件 * 包含高德地图配置、权限管理、地图工具函数等 */ const config = require('../config/config.js'); // 高德地图配置 const MAP_CONFIG = { // 高德地图Key - 需要在高德开放平台申请 amapKey: config.amapKey || '9281427fb1b9c4e1c2acf097a3194781', // 地图默认设置 defaults: { latitude: 39.908823, // 北京天安门 longitude: 116.39747, scale: 16, minScale: 3, maxScale: 20, showLocation: true, showScale: true, showCompass: true, enableOverlooking: false, enableZoom: true, enableScroll: true, enableRotate: false, enable3D: false }, // 定位配置 location: { type: 'gcj02', // 坐标系类型:wgs84、gcj02 isHighAccuracy: true, highAccuracyExpireTime: 4000, timeout: 10000, cacheTimeout: 60000 // 位置缓存时间 }, // 标记点配置 markers: { // 当前用户标记 - 使用默认样式 currentUser: { width: 30, height: 30, anchor: { x: 0.5, y: 1 } }, // 好友标记 - 使用默认样式 friend: { width: 25, height: 25, anchor: { x: 0.5, y: 1 } }, // 陌生人标记 - 使用默认样式 stranger: { width: 20, height: 20, anchor: { x: 0.5, y: 1 } } }, // 地图样式 style: { normal: 'normal', // 普通地图 satellite: 'satellite', // 卫星地图 traffic: 'traffic' // 交通地图 } }; // 权限配置 const PERMISSION_CONFIG = { // 位置权限 location: { scope: 'scope.userLocation', name: '位置信息', description: '用于获取您的位置信息,实现定位和附近功能' }, // 其他权限 camera: { scope: 'scope.camera', name: '摄像头', description: '用于拍照和扫码功能' }, album: { scope: 'scope.album', name: '相册', description: '用于选择图片功能' } }; /** * 地图工具类 */ class MapUtils { /** * 检查位置权限 */ static checkLocationPermission() { return new Promise((resolve, reject) => { wx.getSetting({ success: (res) => { console.log('权限设置:', res.authSetting); if (res.authSetting['scope.userLocation'] === false) { // 用户拒绝过位置权限 reject({ type: 'denied', message: '位置权限被拒绝,请在设置中开启' }); } else if (res.authSetting['scope.userLocation'] === true) { // 用户已授权 resolve(true); } else { // 用户未授权,需要请求授权 resolve(false); } }, fail: (error) => { console.error('获取权限设置失败:', error); reject({ type: 'error', message: '获取权限设置失败' }); } }); }); } /** * 请求位置权限 */ static requestLocationPermission() { return new Promise((resolve, reject) => { wx.authorize({ scope: 'scope.userLocation', success: () => { console.log('位置权限授权成功'); resolve(true); }, fail: (error) => { console.warn('位置权限授权失败:', error); // 引导用户去设置页面 wx.showModal({ title: '位置权限申请', content: 'FindMe需要访问您的位置信息,请在设置中开启位置权限', confirmText: '去设置', cancelText: '取消', success: (res) => { if (res.confirm) { wx.openSetting({ success: (settingRes) => { if (settingRes.authSetting['scope.userLocation']) { resolve(true); } else { reject({ type: 'denied', message: '位置权限被拒绝' }); } }, fail: () => { reject({ type: 'error', message: '打开设置页面失败' }); } }); } else { reject({ type: 'cancelled', message: '用户取消授权' }); } } }); } }); }); } /** * 获取位置(带权限检查) */ static async getLocation(options = {}) { try { // 检查权限 const hasPermission = await this.checkLocationPermission(); if (!hasPermission) { // 请求权限 await this.requestLocationPermission(); } // 获取位置 return new Promise((resolve, reject) => { const locationOptions = { ...MAP_CONFIG.location, ...options, success: (res) => { console.log('获取位置成功:', res); resolve({ latitude: res.latitude, longitude: res.longitude, accuracy: res.accuracy || 0, altitude: res.altitude || 0, speed: res.speed || -1, timestamp: Date.now() }); }, fail: (error) => { console.error('获取位置失败:', error); reject({ type: 'location_error', message: error.errMsg || '定位失败', error: error }); } }; wx.getLocation(locationOptions); }); } catch (error) { console.error('位置获取流程失败:', error); throw error; } } /** * 计算两点距离 */ static calculateDistance(point1, point2) { const lat1 = point1.latitude * Math.PI / 180; const lon1 = point1.longitude * Math.PI / 180; const lat2 = point2.latitude * Math.PI / 180; const lon2 = point2.longitude * Math.PI / 180; const R = 6371000; // 地球半径(米) const dLat = lat2 - lat1; const dLon = lon2 - lon1; const a = Math.sin(dLat/2) * Math.sin(dLat/2) + Math.cos(lat1) * Math.cos(lat2) * Math.sin(dLon/2) * Math.sin(dLon/2); const c = 2 * Math.atan2(Math.sqrt(a), Math.sqrt(1-a)); return R * c; } /** * 格式化距离显示 */ static formatDistance(distance) { if (distance < 1000) { return `${Math.round(distance)}米`; } else if (distance < 10000) { return `${(distance / 1000).toFixed(1)}公里`; } else { return `${Math.round(distance / 1000)}公里`; } } /** * 创建标记点 */ static createMarker(data, type = 'friend') { const markerConfig = MAP_CONFIG.markers[type] || MAP_CONFIG.markers.friend; return { id: data.id || Date.now(), latitude: data.latitude, longitude: data.longitude, width: markerConfig.width, height: markerConfig.height, anchor: markerConfig.anchor, callout: data.showCallout ? { content: data.nickname || '用户', color: '#333333', fontSize: 12, borderRadius: 4, bgColor: '#ffffff', padding: 8, display: 'ALWAYS' } : null, customData: { userId: data.userId, nickname: data.nickname, avatar: data.avatar, distance: data.distance, lastUpdateTime: data.lastUpdateTime } }; } /** * 获取地图区域 */ static getMapRegion(centerPoint, markers = []) { if (markers.length === 0) { return { latitude: centerPoint.latitude, longitude: centerPoint.longitude, scale: MAP_CONFIG.defaults.scale }; } // 计算包含所有标记点的区域 let minLat = centerPoint.latitude; let maxLat = centerPoint.latitude; let minLng = centerPoint.longitude; let maxLng = centerPoint.longitude; markers.forEach(marker => { minLat = Math.min(minLat, marker.latitude); maxLat = Math.max(maxLat, marker.latitude); minLng = Math.min(minLng, marker.longitude); maxLng = Math.max(maxLng, marker.longitude); }); // 添加边距 const latPadding = (maxLat - minLat) * 0.3; const lngPadding = (maxLng - minLng) * 0.3; return { latitude: (minLat + maxLat) / 2, longitude: (minLng + maxLng) / 2, scale: Math.max(Math.min(18 - Math.log2(Math.max(maxLat - minLat + latPadding, maxLng - minLng + lngPadding) * 111000), 18), 8) }; } } module.exports = { MAP_CONFIG, PERMISSION_CONFIG, MapUtils };