| | |
| | | }, |
| | | 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.localLatitude = newVal; |
| | | this.mapLatitude = newVal; |
| | | this.moveToLocation(newVal, this.longitude); |
| | | this.initLocation(); |
| | |
| | | }, |
| | | longitude: { |
| | | handler(newVal) { |
| | | console.log(newVal, '经度'); |
| | | if (newVal && this.latitude && this.isValidLongitude(newVal)) { |
| | | // 只在回显时更新本地坐标 |
| | | this.localLongitude = newVal; |
| | | this.mapLongitude = newVal; |
| | | this.moveToLocation(this.latitude, newVal); |
| | | this.initLocation(); |
| | |
| | | try { |
| | | // 初始化地图上下文 |
| | | this.mapCtx = Taro.createMapContext('map', this); |
| | | |
| | | // 检查地图是否准备就绪 |
| | | this.checkMapReady(); |
| | | } catch (error) { |
| | |
| | | |
| | | // 地图区域改变事件 |
| | | 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, |
| | |
| | | street: address.street, |
| | | streetNumber: address.streetNumber, |
| | | }; |
| | | |
| | | // 添加标记点并显示地址信息 |
| | | this.addMarker(latitude, longitude, address.address); |
| | | // 通知父组件位置已更新 |
| | |
| | | width: 20, |
| | | height: 20, |
| | | callout: { |
| | | content: title, |
| | | content: title || '未知位置', |
| | | color: '#000000', |
| | | fontSize: 14, |
| | | borderRadius: 4, |
| | |
| | | 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: '获取地址失败', |
| | |
| | | }); |
| | | return; |
| | | } |
| | | |
| | | this.currentLocation = { |
| | | latitude, |
| | | longitude, |
| | |
| | | street: address.street, |
| | | streetNumber: address.streetNumber, |
| | | }; |
| | | |
| | | // 添加标记点 |
| | | this.addMarker(latitude, longitude, address.address); |
| | | this.$emit('locationSelected', this.currentLocation); |
| | |
| | | |
| | | // 移动到指定位置 |
| | | 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: res.latitude, |
| | | longitude: res.longitude, |
| | | address: address.address, |
| | | province: address.province, |
| | | city: address.city, |
| | |
| | | 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', |
| | |
| | | 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; |
| | | this.currentLocation = { |
| | | latitude: baiduLocation.lat, |
| | | longitude: baiduLocation.lng, |
| | | latitude: res.latitude, |
| | | longitude: 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', |
| | |
| | | |
| | | // 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 { |
| | | // 将 GCJ-02 坐标转换为百度坐标用于获取地址 |
| | | const baiduCoords = this.gcj02ToBaidu(this.latitude, this.longitude); |
| | | // 获取地址信息 |
| | | const address = await this.getAddressFromLocation( |
| | | this.latitude, |
| | | this.longitude, |
| | | baiduCoords.lat, |
| | | baiduCoords.lng, |
| | | ); |
| | | if (!address || !address.address) { |
| | | return; |
| | | } |
| | | |
| | | // 更新当前位置信息 |
| | | this.currentLocation = { |
| | | latitude: this.latitude, |
| | |
| | | street: address.street, |
| | | streetNumber: address.streetNumber, |
| | | }; |
| | | |
| | | // 添加标记点 |
| | | this.addMarker(this.latitude, this.longitude, address.address); |
| | | // 通知父组件位置已更新 |