From 1ef56b68318629e24f8e42406822059262d392b9 Mon Sep 17 00:00:00 2001 From: coder77 <2293444075@qq.com> Date: Thu, 10 Apr 2025 11:03:25 +0800 Subject: [PATCH] Merge branch 'master_dev' of ssh://dev.zhiheiot.com:29418/mob-components into master_dev --- plugins/baiduMap/CBaiduMap.weapp.vue | 442 +++++++++++++++++++++++++++++++++++------------------- 1 files changed, 284 insertions(+), 158 deletions(-) diff --git a/plugins/baiduMap/CBaiduMap.weapp.vue b/plugins/baiduMap/CBaiduMap.weapp.vue index c7f6728..2491458 100644 --- a/plugins/baiduMap/CBaiduMap.weapp.vue +++ b/plugins/baiduMap/CBaiduMap.weapp.vue @@ -28,7 +28,7 @@ type="primary" size="small" :onClick="evt => handleChooseLocation(evt)" - >选择位置</AtButton> + >选择地点</AtButton> <AtButton type="primary" size="small" @@ -41,7 +41,7 @@ size="small" class="btn-info" :onClick="evt => handleSaveLocation(evt)" - >保存</AtButton> + >确认</AtButton> </view> </view> </view> @@ -51,6 +51,7 @@ import Taro from '@tarojs/taro'; import { AtButton } from 'taro-ui-vue'; import { BAIDU_MAP, BMapWX } from './index'; +import './cBaiduMap.scss'; export default { name: 'CBaiduMap', @@ -69,68 +70,82 @@ }, data() { return { + // 地图上下文 mapCtx: null, + // 地图是否准备就绪 isMapReady: false, + // 当前位置 currentLocation: null, + // 标记点id selectedMarkerId: 0, + // 标记点列表 markers: [], + // 本地维护的坐标 + localLatitude: this.latitude, + localLongitude: this.longitude, + // 地图坐标 mapLatitude: this.latitude, mapLongitude: this.longitude, + // 地图缩放级别 mapScale: 14, + // 是否由chooseLocation触发移动 + isFromChooseLocation: false, }; }, watch: { latitude: { handler(newVal) { - console.log(newVal, '纬度'); if (newVal && this.longitude && this.isValidLatitude(newVal)) { - this.mapLatitude = newVal; + // 只在回显时更新本地坐标 + this.localLatitude = newVal; this.moveToLocation(newVal, this.longitude); - this.initLocation(); } }, - immediate: true, + immediate: false, }, longitude: { handler(newVal) { - console.log(newVal, '经度'); if (newVal && this.latitude && this.isValidLongitude(newVal)) { - this.mapLongitude = newVal; + // 只在回显时更新本地坐标 + this.localLongitude = 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) - ) { - this.initLocation(); - } + // 设置一个延时,确保地图组件已完全加载 + 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.mapCtx = Taro.createMapContext('map', this); - // 检查地图是否准备就绪 this.checkMapReady(); } catch (error) { @@ -154,26 +169,34 @@ // 地图区域改变事件 async handleRegionChange(evt) { + // 如果是由chooseLocation触发的移动,则不处理 + if (this.isFromChooseLocation) { + return; + } if (!evt.detail || !evt.detail.centerLocation) { return; } - const { latitude, longitude } = evt.detail.centerLocation; if (!latitude || !longitude) { return; } - try { + // 将 GCJ-02 坐标转换为百度坐标用于获取地址 + const baiduCoords = this.gcj02ToBaidu(latitude, longitude); // 获取地址信息 - const address = await this.getAddressFromLocation(latitude, longitude); + const address = await this.getAddressFromLocation( + baiduCoords.lat, + baiduCoords.lng, + ); if (!address || !address.address) { return; } - // 更新当前位置信息 this.currentLocation = { - latitude, - longitude, + latitude: baiduCoords.lat, + longitude: baiduCoords.lng, + gcjLatitude: latitude, + gcjLongitude: longitude, address: address.address, province: address.province, city: address.city, @@ -181,7 +204,6 @@ street: address.street, streetNumber: address.streetNumber, }; - // 添加标记点并显示地址信息 this.addMarker(latitude, longitude, address.address); // 通知父组件位置已更新 @@ -204,7 +226,7 @@ width: 20, height: 20, callout: { - content: title, + content: title || '未知位置', color: '#000000', fontSize: 14, borderRadius: 4, @@ -224,16 +246,21 @@ if (!e || !e.detail) { return; } - const { latitude, longitude } = e.detail; if (!latitude || !longitude) { return; } - try { + // 更新本地坐标 + this.localLatitude = latitude; + this.localLongitude = longitude; + // 将 GCJ-02 坐标转换为百度坐标用于获取地址 + const baiduCoords = this.gcj02ToBaidu(latitude, longitude); // 获取地址信息 - const address = await this.getAddressFromLocation(latitude, longitude); - + const address = await this.getAddressFromLocation( + baiduCoords.lat, + baiduCoords.lng, + ); if (!address || !address.address) { Taro.showToast({ title: '获取地址失败', @@ -241,10 +268,11 @@ }); return; } - this.currentLocation = { - latitude, - longitude, + latitude: baiduCoords.lat, + longitude: baiduCoords.lng, + gcjLatitude: latitude, + gcjLongitude: longitude, address: address.address, province: address.province, city: address.city, @@ -252,7 +280,6 @@ street: address.street, streetNumber: address.streetNumber, }; - // 添加标记点 this.addMarker(latitude, longitude, address.address); this.$emit('locationSelected', this.currentLocation); @@ -270,14 +297,18 @@ 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, @@ -291,36 +322,72 @@ // 移动到指定位置 moveToLocation(latitude, longitude) { - // 更新地图位置 + // 更新地图位置数据 this.mapLatitude = latitude; this.mapLongitude = longitude; this.mapScale = 16; // 设置合适的缩放级别 - - // 更新标记点位置 - if (this.currentLocation) { - this.addMarker(latitude, longitude, this.currentLocation.address); + // 使用地图上下文移动到指定位置 + if (this.mapCtx) { + this.mapCtx.moveToLocation({ + latitude: latitude, + longitude: longitude, + success: () => { + // 更新标记点位置 + if (this.currentLocation) { + this.addMarker( + latitude, + longitude, + this.currentLocation.address, + ); + } + }, + fail: err => { + console.error('移动失败:', err); + // 失败时也要尝试更新标记点 + if (this.currentLocation) { + this.addMarker( + latitude, + longitude, + this.currentLocation.address, + ); + } + }, + }); + } else { + // 地图上下文不可用时,直接更新标记点 + if (this.currentLocation) { + this.addMarker(latitude, longitude, this.currentLocation.address); + } } }, // 获取当前位置按钮点击事件 async handleGetLocation(e) { try { + // 显示加载中提示 + Taro.showLoading({ + title: '获取位置中...', + }); const res = await Taro.getLocation({ type: 'gcj02', }); - - // 将GCJ-02坐标转换为百度坐标 - const baiduLocation = this.gcj02ToBaidu(res.latitude, res.longitude); - + // 更新本地坐标 + this.localLatitude = res.latitude; + this.localLongitude = res.longitude; + // 设置标志,防止handleRegionChange触发时覆盖地址 + this.isFromChooseLocation = true; + // 将 GCJ-02 坐标转换为百度坐标用于获取地址 + const baiduCoords = this.gcj02ToBaidu(res.latitude, res.longitude); // 获取地址信息 const address = await this.getAddressFromLocation( - baiduLocation.lat, - baiduLocation.lng, + baiduCoords.lat, + baiduCoords.lng, ); - this.currentLocation = { - latitude: baiduLocation.lat, - longitude: baiduLocation.lng, + latitude: baiduCoords.lat, + longitude: baiduCoords.lng, + gcjLatitude: res.latitude, + gcjLongitude: res.longitude, address: address.address, province: address.province, city: address.city, @@ -328,12 +395,24 @@ street: address.street, streetNumber: address.streetNumber, }; - - // 移动到当前位置(使用原始GCJ-02坐标) - this.moveToLocation(res.latitude, res.longitude); + // 直接更新地图位置 + this.mapLatitude = res.latitude; + this.mapLongitude = res.longitude; + this.mapScale = 16; + // 添加标记点 + this.addMarker(res.latitude, res.longitude, address.address); + // 通知父组件位置已更新 this.$emit('locationSelected', this.currentLocation); + // 完成后隐藏加载提示 + Taro.hideLoading(); + // 使用延时恢复标志 + setTimeout(() => { + this.isFromChooseLocation = false; + }, 800); } catch (error) { console.error('获取位置失败:', error); + Taro.hideLoading(); + this.isFromChooseLocation = false; Taro.showToast({ title: '获取位置失败', icon: 'none', @@ -345,26 +424,56 @@ async handleChooseLocation(e) { try { const res = await Taro.chooseLocation(); - - // 将GCJ-02坐标转换为百度坐标 - const baiduLocation = this.gcj02ToBaidu(res.latitude, res.longitude); - + // 设置标志,防止handleRegionChange触发时覆盖地址 + this.isFromChooseLocation = true; + // 更新本地坐标 + this.localLatitude = res.latitude; + this.localLongitude = res.longitude; + // 转换为百度坐标 + const baiduCoords = this.gcj02ToBaidu(res.latitude, res.longitude); this.currentLocation = { - latitude: baiduLocation.lat, - longitude: baiduLocation.lng, + latitude: baiduCoords.lat, + longitude: baiduCoords.lng, + gcjLatitude: res.latitude, + gcjLongitude: res.longitude, address: res.address, + name: res.name || '', province: '', city: '', district: '', street: '', streetNumber: '', }; - - // 移动到选择的位置(使用原始GCJ-02坐标) - this.moveToLocation(res.latitude, res.longitude); + // 直接更新地图位置和添加标记点 + this.mapLatitude = res.latitude; + this.mapLongitude = res.longitude; + this.mapScale = 16; + // 添加标记点 + this.addMarker(res.latitude, res.longitude, res.address); + // 使用地图上下文移动到选择的位置 + if (this.mapCtx) { + this.mapCtx.moveToLocation({ + latitude: res.latitude, + longitude: res.longitude, + success: () => { + // 再次确保标记点显示 + setTimeout(() => { + // 重置标志 + this.isFromChooseLocation = false; + }, 800); + }, + fail: err => { + console.error('移动失败:', err); + // 重置标志 + this.isFromChooseLocation = false; + }, + }); + } this.$emit('locationSelected', this.currentLocation); } catch (error) { console.error('选择位置失败:', error); + // 重置标志 + this.isFromChooseLocation = false; Taro.showToast({ title: '选择位置失败', icon: 'none', @@ -397,11 +506,9 @@ }, timeout: 10000, }); - if (!res.data) { throw new Error('百度地图API返回数据为空'); } - if (res.data.status === 0) { const result = res.data.result; return { @@ -430,116 +537,135 @@ // GCJ-02坐标转百度坐标 gcj02ToBaidu(lat, lng) { - const x_pi = (3.14159265358979324 * 3000.0) / 180.0; - const x = lng; - const y = lat; - const z = Math.sqrt(x * x + y * y) + 0.00002 * Math.sin(y * x_pi); - const theta = Math.atan2(y, x) + 0.000003 * Math.cos(x * x_pi); - const lngs = z * Math.cos(theta); - const lats = z * Math.sin(theta); + const PI = 3.14159265358979324; + const x_pi = (PI * 3000.0) / 180.0; + const z = Math.sqrt(lng * lng + lat * lat) + 0.00002 * Math.sin(lat * x_pi); + const theta = Math.atan2(lat, lng) + 0.000003 * Math.cos(lng * x_pi); + const bd_lng = z * Math.cos(theta) + 0.0065; + const bd_lat = z * Math.sin(theta) + 0.006; return { - lat: lats, - lng: lngs, + lat: bd_lat, + lng: bd_lng, }; }, // 百度坐标转腾讯坐标 baiduToGcj02(lat, lng) { - const x_pi = (3.14159265358979324 * 3000.0) / 180.0; + const PI = 3.14159265358979324; + const x_pi = (PI * 3000.0) / 180.0; const x = lng - 0.0065; const y = lat - 0.006; const z = Math.sqrt(x * x + y * y) - 0.00002 * Math.sin(y * x_pi); const theta = Math.atan2(y, x) - 0.000003 * Math.cos(x * x_pi); - const lngs = z * Math.cos(theta); - const lats = z * Math.sin(theta); + const gg_lng = z * Math.cos(theta); + const gg_lat = z * Math.sin(theta); return { - lat: lats, - lng: lngs, + lat: gg_lat, + lng: gg_lng, }; }, // 初始化位置信息 async initLocation() { try { - // 获取地址信息 - const address = await this.getAddressFromLocation( - this.latitude, - this.longitude, - ); - if (!address || !address.address) { - return; + // 设置标志,防止handleRegionChange触发时覆盖地址 + this.isFromChooseLocation = true; + // 显示加载提示 + Taro.showLoading({ + title: '加载位置信息...', + }); + try { + // 使用本地坐标(初始默认值或props传入值)获取地址信息 + const address = await this.getAddressFromLocation( + 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.localLatitude, + longitude: this.localLongitude, + gcjLatitude: gcjCoords.lat, + gcjLongitude: gcjCoords.lng, + address: address.address, + province: address.province, + city: address.city, + district: address.district, + street: address.street, + streetNumber: address.streetNumber, + }; + // 使用腾讯坐标更新地图位置 + this.mapLatitude = gcjCoords.lat; + this.mapLongitude = gcjCoords.lng; + this.mapScale = 16; + // 添加标记点 + 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); + Taro.hideLoading(); + this.isFromChooseLocation = false; } - - // 更新当前位置信息 - this.currentLocation = { - latitude: this.latitude, - longitude: this.longitude, - address: address.address, - province: address.province, - city: address.city, - district: address.district, - street: address.street, - streetNumber: address.streetNumber, - }; - - // 添加标记点 - this.addMarker(this.latitude, this.longitude, address.address); - // 通知父组件位置已更新 - this.$emit('locationSelected', this.currentLocation); } catch (error) { - console.error('初始化位置信息失败:', 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> \ No newline at end of file +</script> \ No newline at end of file -- Gitblit v1.9.1