// 高德静态地图API工具类 const AMAP_KEY = '4c513a688938fd89b88b296e867f66ec' class StaticMapUtil { constructor() { this.key = AMAP_KEY this.baseUrl = 'https://restapi.amap.com/v3/staticmap' } /** * 生成静态地图URL * @param {Object} options 地图配置选项 * @returns {String} 静态地图URL */ generateMapUrl(options = {}) { const defaultOptions = { location: '116.397128,39.916527', // 默认中心点(北京) zoom: 13, // 缩放级别 size: '750*500', // 图片尺寸 scale: 2, // 高清显示 markers: [], // 标记点 labels: [], // 文字标注 paths: [], // 路径 traffic: 0, // 交通路况 0-不显示 1-显示 format: 'png' // 图片格式 } const config = { ...defaultOptions, ...options } let url = `${this.baseUrl}?key=${this.key}` url += `&location=${config.location}` url += `&zoom=${config.zoom}` url += `&size=${config.size}` url += `&scale=${config.scale}` url += `&traffic=${config.traffic}` url += `&format=${config.format}` // 添加标记点 if (config.markers && config.markers.length > 0) { const markersStr = config.markers.map(marker => { let markerStr = '' if (marker.size) markerStr += `size:${marker.size}|` if (marker.color) markerStr += `color:${marker.color}|` if (marker.label) markerStr += `label:${marker.label}|` markerStr += `${marker.longitude},${marker.latitude}` return markerStr }).join('|') url += `&markers=${encodeURIComponent(markersStr)}` } // 添加文字标注 if (config.labels && config.labels.length > 0) { const labelsStr = config.labels.map(label => { let labelStr = '' if (label.content) labelStr += `content:${label.content}|` if (label.font) labelStr += `font:${label.font}|` if (label.bold) labelStr += `bold:${label.bold}|` if (label.fontSize) labelStr += `fontSize:${label.fontSize}|` if (label.fontColor) labelStr += `fontColor:${label.fontColor}|` if (label.background) labelStr += `background:${label.background}|` labelStr += `${label.longitude},${label.latitude}` return labelStr }).join('|') url += `&labels=${encodeURIComponent(labelsStr)}` } return url } /** * 为场地列表生成静态地图URL * @param {Array} positions 场地列表 * @param {Object} options 额外选项 * @returns {String} 静态地图URL */ generatePositionsMapUrl(positions = [], options = {}) { if (!positions || positions.length === 0) { return this.generateMapUrl(options) } // 计算地图中心点和缩放级别 const center = this.calculateCenter(positions) const zoom = this.calculateOptimalZoom(positions, center) // 生成标记点 const markers = positions.map((position, index) => ({ longitude: parseFloat(position.longitude), latitude: parseFloat(position.latitude), size: 'mid', color: position.status === 'online' ? 'green' : 'red', label: String.fromCharCode(65 + (index % 26)) // A, B, C... })) return this.generateMapUrl({ location: `${center.longitude},${center.latitude}`, zoom: zoom, markers: markers, ...options }) } /** * 计算多个点的中心位置 * @param {Array} positions 位置数组 * @returns {Object} 中心点坐标 */ calculateCenter(positions) { if (positions.length === 0) { return { longitude: 116.397128, latitude: 39.916527 } } const validPositions = positions.filter(p => p.longitude && p.latitude) if (validPositions.length === 0) { return { longitude: 116.397128, latitude: 39.916527 } } const sum = validPositions.reduce((acc, pos) => ({ longitude: acc.longitude + parseFloat(pos.longitude), latitude: acc.latitude + parseFloat(pos.latitude) }), { longitude: 0, latitude: 0 }) return { longitude: (sum.longitude / validPositions.length).toFixed(6), latitude: (sum.latitude / validPositions.length).toFixed(6) } } /** * 计算最佳缩放级别 * @param {Array} positions 位置数组 * @param {Object} center 中心点 * @returns {Number} 缩放级别 */ calculateOptimalZoom(positions, center) { if (positions.length <= 1) return 15 const validPositions = positions.filter(p => p.longitude && p.latitude) if (validPositions.length <= 1) return 15 // 计算最大距离 let maxDistance = 0 validPositions.forEach(pos => { const distance = this.getDistance( center.latitude, center.longitude, parseFloat(pos.latitude), parseFloat(pos.longitude) ) maxDistance = Math.max(maxDistance, distance) }) // 根据最大距离确定缩放级别 if (maxDistance < 1) return 16 // 1km内 if (maxDistance < 2) return 15 // 2km内 if (maxDistance < 5) return 14 // 5km内 if (maxDistance < 10) return 13 // 10km内 if (maxDistance < 20) return 12 // 20km内 if (maxDistance < 50) return 11 // 50km内 return 10 // 50km以上 } /** * 计算两点间距离(公里) * @param {Number} lat1 纬度1 * @param {Number} lng1 经度1 * @param {Number} lat2 纬度2 * @param {Number} lng2 经度2 * @returns {Number} 距离(公里) */ getDistance(lat1, lng1, lat2, lng2) { const radLat1 = lat1 * Math.PI / 180.0 const radLat2 = lat2 * Math.PI / 180.0 const a = radLat1 - radLat2 const b = lng1 * Math.PI / 180.0 - lng2 * Math.PI / 180.0 let s = 2 * Math.asin(Math.sqrt(Math.pow(Math.sin(a / 2), 2) + Math.cos(radLat1) * Math.cos(radLat2) * Math.pow(Math.sin(b / 2), 2))) s = s * 6378.137 s = Math.round(s * 10000) / 10000 return s } /** * 预加载地图图片 * @param {String} mapUrl 地图URL * @returns {Promise} 图片加载Promise */ preloadMapImage(mapUrl) { return new Promise((resolve, reject) => { const img = new Image() img.onload = () => resolve(mapUrl) img.onerror = reject img.src = mapUrl }) } } export default new StaticMapUtil()