| | |
| | | import Taro from '@tarojs/taro'; |
| | | import { AtButton } from 'taro-ui-vue'; |
| | | import { BAIDU_MAP, BMapWX } from './index'; |
| | | import './cBaiduMap.scss'; |
| | | |
| | | export default { |
| | | name: 'CBaiduMap', |
| | |
| | | if (newVal && this.longitude && this.isValidLatitude(newVal)) { |
| | | // 只在回显时更新本地坐标 |
| | | this.localLatitude = newVal; |
| | | this.mapLatitude = newVal; |
| | | this.moveToLocation(newVal, this.longitude); |
| | | this.initLocation(); |
| | | } |
| | | }, |
| | | immediate: true, |
| | | immediate: false, |
| | | }, |
| | | longitude: { |
| | | handler(newVal) { |
| | | if (newVal && this.latitude && this.isValidLongitude(newVal)) { |
| | | // 只在回显时更新本地坐标 |
| | | this.localLongitude = newVal; |
| | | this.mapLongitude = newVal; |
| | | this.moveToLocation(this.latitude, newVal); |
| | | this.initLocation(); |
| | | } |
| | | }, |
| | | immediate: true, |
| | | immediate: false, |
| | | }, |
| | | }, |
| | | mounted() { |
| | | // 初始化地图 |
| | | this.initMap(); |
| | | // 如果有初始经纬度,添加标记点 |
| | | if ( |
| | | this.latitude && |
| | | this.longitude && |
| | | this.isValidLatitude(this.latitude) && |
| | | this.isValidLongitude(this.longitude) |
| | | ) { |
| | | // 设置一个延时,确保地图组件已完全加载 |
| | | setTimeout(() => { |
| | | // 使用默认值处理可能的undefined或null |
| | | const latitude = this.latitude || 39.90886; |
| | | const longitude = this.longitude || 116.39739; |
| | | // 确保坐标有效 |
| | | if (this.isValidLatitude(latitude) && this.isValidLongitude(longitude)) { |
| | | this.localLatitude = latitude; |
| | | this.localLongitude = longitude; |
| | | this.initLocation(); |
| | | } |
| | | }, 800); |
| | | }, |
| | | methods: { |
| | | // 验证纬度是否有效 |
| | | isValidLatitude(lat) { |
| | | return lat >= -90 && lat <= 90; |
| | | }, |
| | | |
| | | // 验证经度是否有效 |
| | | isValidLongitude(lng) { |
| | | return lng >= -180 && lng <= 180; |
| | | }, |
| | | |
| | | // 初始化地图 |
| | | initMap() { |
| | | try { |
| | |
| | | } |
| | | // 更新当前位置信息 |
| | | this.currentLocation = { |
| | | latitude, |
| | | longitude, |
| | | latitude: baiduCoords.lat, |
| | | longitude: baiduCoords.lng, |
| | | gcjLatitude: latitude, |
| | | gcjLongitude: longitude, |
| | | address: address.address, |
| | | province: address.province, |
| | | city: address.city, |
| | |
| | | return; |
| | | } |
| | | this.currentLocation = { |
| | | latitude, |
| | | longitude, |
| | | latitude: baiduCoords.lat, |
| | | longitude: baiduCoords.lng, |
| | | gcjLatitude: latitude, |
| | | gcjLongitude: longitude, |
| | | address: address.address, |
| | | province: address.province, |
| | | city: address.city, |
| | |
| | | const { markerId } = e.detail; |
| | | const marker = this.markers.find(m => m.id === markerId); |
| | | if (marker) { |
| | | // 转换为百度坐标 |
| | | const baiduCoords = this.gcj02ToBaidu(marker.latitude, marker.longitude); |
| | | // 获取地址信息 |
| | | const address = await this.getAddressFromLocation( |
| | | marker.latitude, |
| | | marker.longitude, |
| | | baiduCoords.lat, |
| | | baiduCoords.lng, |
| | | ); |
| | | this.currentLocation = { |
| | | latitude: marker.latitude, |
| | | longitude: marker.longitude, |
| | | latitude: baiduCoords.lat, |
| | | longitude: baiduCoords.lng, |
| | | gcjLatitude: marker.latitude, |
| | | gcjLongitude: marker.longitude, |
| | | address: address.address, |
| | | province: address.province, |
| | | city: address.city, |
| | |
| | | this.mapLatitude = latitude; |
| | | this.mapLongitude = longitude; |
| | | this.mapScale = 16; // 设置合适的缩放级别 |
| | | |
| | | // 使用地图上下文移动到指定位置 |
| | | if (this.mapCtx) { |
| | | this.mapCtx.moveToLocation({ |
| | |
| | | baiduCoords.lng, |
| | | ); |
| | | this.currentLocation = { |
| | | latitude: res.latitude, |
| | | longitude: res.longitude, |
| | | latitude: baiduCoords.lat, |
| | | longitude: baiduCoords.lng, |
| | | gcjLatitude: res.latitude, |
| | | gcjLongitude: res.longitude, |
| | | address: address.address, |
| | | province: address.province, |
| | | city: address.city, |
| | |
| | | // 更新本地坐标 |
| | | this.localLatitude = res.latitude; |
| | | this.localLongitude = res.longitude; |
| | | // 转换为百度坐标 |
| | | const baiduCoords = this.gcj02ToBaidu(res.latitude, res.longitude); |
| | | this.currentLocation = { |
| | | latitude: res.latitude, |
| | | longitude: res.longitude, |
| | | latitude: baiduCoords.lat, |
| | | longitude: baiduCoords.lng, |
| | | gcjLatitude: res.latitude, |
| | | gcjLongitude: res.longitude, |
| | | address: res.address, |
| | | name: res.name || '', |
| | | province: '', |
| | |
| | | }, |
| | | timeout: 10000, |
| | | }); |
| | | |
| | | if (!res.data) { |
| | | throw new Error('百度地图API返回数据为空'); |
| | | } |
| | | |
| | | if (res.data.status === 0) { |
| | | const result = res.data.result; |
| | | return { |
| | |
| | | // 初始化位置信息 |
| | | async initLocation() { |
| | | try { |
| | | // 将 GCJ-02 坐标转换为百度坐标用于获取地址 |
| | | const baiduCoords = this.gcj02ToBaidu(this.latitude, this.longitude); |
| | | // 获取地址信息 |
| | | // 设置标志,防止handleRegionChange触发时覆盖地址 |
| | | this.isFromChooseLocation = true; |
| | | // 显示加载提示 |
| | | Taro.showLoading({ |
| | | title: '加载位置信息...', |
| | | }); |
| | | try { |
| | | // 使用本地坐标(初始默认值或props传入值)获取地址信息 |
| | | const address = await this.getAddressFromLocation( |
| | | baiduCoords.lat, |
| | | baiduCoords.lng, |
| | | this.localLatitude, |
| | | this.localLongitude, |
| | | ); |
| | | if (!address || !address.address) { |
| | | console.warn('获取地址信息失败'); |
| | | Taro.hideLoading(); |
| | | this.isFromChooseLocation = false; |
| | | return; |
| | | } |
| | | // 将百度坐标转换为腾讯坐标 |
| | | const gcjCoords = this.baiduToGcj02( |
| | | this.localLatitude, |
| | | this.localLongitude, |
| | | ); |
| | | // 更新当前位置信息 |
| | | this.currentLocation = { |
| | | latitude: this.latitude, |
| | | longitude: this.longitude, |
| | | latitude: this.localLatitude, |
| | | longitude: this.localLongitude, |
| | | gcjLatitude: gcjCoords.lat, |
| | | gcjLongitude: gcjCoords.lng, |
| | | address: address.address, |
| | | province: address.province, |
| | | city: address.city, |
| | |
| | | street: address.street, |
| | | streetNumber: address.streetNumber, |
| | | }; |
| | | // 使用腾讯坐标更新地图位置 |
| | | this.mapLatitude = gcjCoords.lat; |
| | | this.mapLongitude = gcjCoords.lng; |
| | | this.mapScale = 16; |
| | | // 添加标记点 |
| | | this.addMarker(this.latitude, this.longitude, address.address); |
| | | this.markers = [ |
| | | { |
| | | id: this.selectedMarkerId++, |
| | | latitude: gcjCoords.lat, |
| | | longitude: gcjCoords.lng, |
| | | title: address.address, |
| | | width: 30, |
| | | height: 30, |
| | | callout: { |
| | | content: address.address || '未知位置', |
| | | color: '#000000', |
| | | fontSize: 14, |
| | | borderRadius: 4, |
| | | padding: 8, |
| | | display: 'ALWAYS', |
| | | bgColor: '#ffffff', |
| | | borderWidth: 1, |
| | | borderColor: '#cccccc', |
| | | textAlign: 'center', |
| | | anchorY: -10, |
| | | }, |
| | | }, |
| | | ]; |
| | | // 通知父组件位置已更新 |
| | | this.$emit('locationSelected', this.currentLocation); |
| | | // 隐藏加载提示 |
| | | Taro.hideLoading(); |
| | | // 使用地图上下文移动到位置中心 |
| | | if (this.mapCtx) { |
| | | this.mapCtx.moveToLocation({ |
| | | latitude: gcjCoords.lat, |
| | | longitude: gcjCoords.lng, |
| | | success: () => { |
| | | // 延迟重置标志 |
| | | setTimeout(() => { |
| | | this.isFromChooseLocation = false; |
| | | }, 800); |
| | | }, |
| | | fail: err => { |
| | | console.error('地图移动失败:', err); |
| | | this.isFromChooseLocation = false; |
| | | }, |
| | | }); |
| | | } else { |
| | | this.isFromChooseLocation = false; |
| | | } |
| | | } catch (error) { |
| | | console.error('初始化位置信息失败:', error); |
| | | console.error('处理位置信息失败:', error); |
| | | Taro.hideLoading(); |
| | | this.isFromChooseLocation = false; |
| | | } |
| | | } catch (error) { |
| | | console.error('初始化位置信息失败:', error); |
| | | Taro.hideLoading(); |
| | | this.isFromChooseLocation = false; |
| | | } |
| | | }, |
| | | }, |
| | | }; |
| | | </script> |
| | | |
| | | <style lang="scss"> |
| | | .c-baidu-map { |
| | | width: 100%; |
| | | height: 100%; |
| | | position: relative; |
| | | display: block; |
| | | |
| | | .map { |
| | | width: 100%; |
| | | height: 100%; |
| | | display: block; |
| | | } |
| | | |
| | | .map-controls { |
| | | position: absolute; |
| | | bottom: 0; |
| | | left: 0; |
| | | right: 0; |
| | | background: rgba(255, 255, 255, 0.9); |
| | | z-index: 100; |
| | | |
| | | .map-controls-top { |
| | | display: flex; |
| | | justify-content: space-between; |
| | | align-items: center; |
| | | height: 100px; |
| | | padding: 0 20px; |
| | | .at-button { |
| | | width: 45%; |
| | | height: 76px !important; |
| | | line-height: 72px; |
| | | font-size: 40px; |
| | | } |
| | | } |
| | | .map-controls-bottom { |
| | | display: flex; |
| | | align-items: center; |
| | | height: 100px; |
| | | padding: 0 20px; |
| | | .at-button { |
| | | width: 95%; |
| | | height: 76px !important; |
| | | line-height: 72px; |
| | | font-size: 40px; |
| | | } |
| | | } |
| | | } |
| | | } |
| | | </style> |