findme-miniprogram-frontend/utils/map-config.js
2025-12-27 17:16:03 +08:00

336 lines
8.4 KiB
JavaScript
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

/**
* 地图配置文件
* 包含高德地图配置、权限管理、地图工具函数等
*/
const config = require('../config/config.js');
// 高德地图配置
const MAP_CONFIG = {
// 高德地图Key - 需要在高德开放平台申请
// 注意:下方为示例密钥,可能已过期或限制使用,请申请自己的密钥
amapKey: config.amapKey || '9207c12fec275ea84090280f693b88c6',
// 地图默认设置
defaults: {
latitude: 39.908823, // 北京天安门
longitude: 116.39747,
scale: 16,
minScale: 3,
maxScale: 22,
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) => {
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: () => {
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) => {
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
};