From 32b09ee84d7187800a7a10f2264b8b4e30fc574a Mon Sep 17 00:00:00 2001 From: ‘chensiAb’ <‘chenchenco03@163.com’> Date: Mon, 31 Mar 2025 16:35:18 +0800 Subject: [PATCH] feat:测试腾讯地图和百度api的转换 --- plugins/baiduMap/CBaiduMap.weapp.vue | 545 ++++++++++++++++++++++++++++++++++ plugins/baiduMap/bmap-wx.min.js | 356 ++++++++++++++++++++++ plugins/baiduMap/index.js | 13 plugins/baiduMap/config.js | 13 4 files changed, 927 insertions(+), 0 deletions(-) diff --git a/plugins/baiduMap/CBaiduMap.weapp.vue b/plugins/baiduMap/CBaiduMap.weapp.vue new file mode 100644 index 0000000..c7f6728 --- /dev/null +++ b/plugins/baiduMap/CBaiduMap.weapp.vue @@ -0,0 +1,545 @@ +/** + * CBaiduMap - 百度地图组件 + * @author chensi + */ + +<template> + <view class="c-baidu-map"> + <map + id="map" + class="map" + :latitude="mapLatitude" + :longitude="mapLongitude" + :markers="markers" + :scale="mapScale" + show-location + enable-rotate + enable-satellite + enable-traffic + enable-3D + enable-building + @tap="evt => handleMapTap(evt)" + @markertap="evt => handleMarkerTap(evt)" + @regionchange="evt => handleRegionChange(evt)" + ></map> + <view class="map-controls"> + <view class="map-controls-top"> + <AtButton + type="primary" + size="small" + :onClick="evt => handleChooseLocation(evt)" + >选择位置</AtButton> + <AtButton + type="primary" + size="small" + :onClick="evt => handleGetLocation(evt)" + >获取当前位置</AtButton> + </view> + <view class="map-controls-bottom"> + <AtButton + type="primary" + size="small" + class="btn-info" + :onClick="evt => handleSaveLocation(evt)" + >保存</AtButton> + </view> + </view> + </view> +</template> + +<script> +import Taro from '@tarojs/taro'; +import { AtButton } from 'taro-ui-vue'; +import { BAIDU_MAP, BMapWX } from './index'; + +export default { + name: 'CBaiduMap', + components: { + AtButton, + }, + props: { + latitude: { + type: Number, + default: 39.90886, + }, + longitude: { + type: Number, + default: 116.39739, + }, + }, + data() { + return { + mapCtx: null, + isMapReady: false, + currentLocation: null, + selectedMarkerId: 0, + markers: [], + mapLatitude: this.latitude, + mapLongitude: this.longitude, + mapScale: 14, + }; + }, + watch: { + latitude: { + handler(newVal) { + console.log(newVal, '纬度'); + if (newVal && this.longitude && this.isValidLatitude(newVal)) { + this.mapLatitude = newVal; + this.moveToLocation(newVal, this.longitude); + this.initLocation(); + } + }, + immediate: true, + }, + longitude: { + handler(newVal) { + console.log(newVal, '经度'); + if (newVal && this.latitude && this.isValidLongitude(newVal)) { + this.mapLongitude = newVal; + this.moveToLocation(this.latitude, newVal); + this.initLocation(); + } + }, + immediate: true, + }, + }, + mounted() { + // 初始化地图 + this.initMap(); + // 如果有初始经纬度,添加标记点 + if ( + this.latitude && + this.longitude && + this.isValidLatitude(this.latitude) && + this.isValidLongitude(this.longitude) + ) { + this.initLocation(); + } + }, + 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) { + console.error('初始化地图失败:', error); + } + }, + + // 检查地图是否准备就绪 + checkMapReady() { + if (this.mapCtx) { + this.mapCtx.getCenterLocation({ + success: res => { + this.isMapReady = true; + }, + fail: err => { + console.error('获取地图中心点失败:', err); + }, + }); + } + }, + + // 地图区域改变事件 + async handleRegionChange(evt) { + if (!evt.detail || !evt.detail.centerLocation) { + return; + } + + const { latitude, longitude } = evt.detail.centerLocation; + if (!latitude || !longitude) { + return; + } + + try { + // 获取地址信息 + const address = await this.getAddressFromLocation(latitude, longitude); + if (!address || !address.address) { + return; + } + + // 更新当前位置信息 + this.currentLocation = { + latitude, + longitude, + address: address.address, + province: address.province, + city: address.city, + district: address.district, + street: address.street, + streetNumber: address.streetNumber, + }; + + // 添加标记点并显示地址信息 + this.addMarker(latitude, longitude, address.address); + // 通知父组件位置已更新 + this.$emit('locationSelected', this.currentLocation); + } catch (error) { + console.error('处理地图区域改变事件失败:', error); + } + }, + + // 添加标记点 + addMarker(latitude, longitude, title = '') { + // 清除之前的标记点 + this.markers = []; + // 添加新的标记点 + this.markers.push({ + id: this.selectedMarkerId++, + latitude, + longitude, + title, + width: 20, + height: 20, + callout: { + content: title, + color: '#000000', + fontSize: 14, + borderRadius: 4, + padding: 8, + display: 'ALWAYS', // 始终显示 + bgColor: '#ffffff', // 背景色 + borderWidth: 1, // 边框宽度 + borderColor: '#cccccc', // 边框颜色 + textAlign: 'center', // 文字居中 + anchorY: -10, // 向上偏移,使文字显示在标记点上方 + }, + }); + }, + + // 地图点击事件 + async handleMapTap(e) { + if (!e || !e.detail) { + return; + } + + const { latitude, longitude } = e.detail; + if (!latitude || !longitude) { + return; + } + + try { + // 获取地址信息 + const address = await this.getAddressFromLocation(latitude, longitude); + + if (!address || !address.address) { + Taro.showToast({ + title: '获取地址失败', + icon: 'none', + }); + return; + } + + this.currentLocation = { + latitude, + longitude, + address: address.address, + province: address.province, + city: address.city, + district: address.district, + street: address.street, + streetNumber: address.streetNumber, + }; + + // 添加标记点 + this.addMarker(latitude, longitude, address.address); + this.$emit('locationSelected', this.currentLocation); + } catch (error) { + console.error('处理地图点击事件失败:', error); + Taro.showToast({ + title: '获取地址失败', + icon: 'none', + }); + } + }, + + // 标记点点击事件 + async handleMarkerTap(e) { + const { markerId } = e.detail; + const marker = this.markers.find(m => m.id === markerId); + if (marker) { + // 获取地址信息 + const address = await this.getAddressFromLocation( + marker.latitude, + marker.longitude, + ); + this.currentLocation = { + latitude: marker.latitude, + longitude: marker.longitude, + address: address.address, + province: address.province, + city: address.city, + district: address.district, + street: address.street, + streetNumber: address.streetNumber, + }; + 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); + } + }, + + // 获取当前位置按钮点击事件 + async handleGetLocation(e) { + try { + const res = await Taro.getLocation({ + type: 'gcj02', + }); + + // 将GCJ-02坐标转换为百度坐标 + const baiduLocation = this.gcj02ToBaidu(res.latitude, res.longitude); + + // 获取地址信息 + const address = await this.getAddressFromLocation( + baiduLocation.lat, + baiduLocation.lng, + ); + + this.currentLocation = { + latitude: baiduLocation.lat, + longitude: baiduLocation.lng, + address: address.address, + province: address.province, + city: address.city, + district: address.district, + street: address.street, + streetNumber: address.streetNumber, + }; + + // 移动到当前位置(使用原始GCJ-02坐标) + this.moveToLocation(res.latitude, res.longitude); + this.$emit('locationSelected', this.currentLocation); + } catch (error) { + console.error('获取位置失败:', error); + Taro.showToast({ + title: '获取位置失败', + icon: 'none', + }); + } + }, + + // 选择位置按钮点击事件 + async handleChooseLocation(e) { + try { + const res = await Taro.chooseLocation(); + + // 将GCJ-02坐标转换为百度坐标 + const baiduLocation = this.gcj02ToBaidu(res.latitude, res.longitude); + + this.currentLocation = { + latitude: baiduLocation.lat, + longitude: baiduLocation.lng, + address: res.address, + province: '', + city: '', + district: '', + street: '', + streetNumber: '', + }; + + // 移动到选择的位置(使用原始GCJ-02坐标) + this.moveToLocation(res.latitude, res.longitude); + this.$emit('locationSelected', this.currentLocation); + } catch (error) { + console.error('选择位置失败:', error); + Taro.showToast({ + title: '选择位置失败', + icon: 'none', + }); + } + }, + + // 保存位置按钮点击事件 + handleSaveLocation(e) { + if (!this.currentLocation) { + Taro.showToast({ + title: '请先选择位置', + icon: 'none', + }); + return; + } + this.$emit('saveLocation', this.currentLocation); + }, + + // 获取地址信息 + async getAddressFromLocation(latitude, longitude) { + try { + const res = await Taro.request({ + url: `${BAIDU_MAP.apiUrl}/reverse_geocoding/v3/`, + data: { + ak: BAIDU_MAP.ak, + output: 'json', + coordtype: BAIDU_MAP.coordType, + location: `${latitude},${longitude}`, + }, + timeout: 10000, + }); + + if (!res.data) { + throw new Error('百度地图API返回数据为空'); + } + + if (res.data.status === 0) { + const result = res.data.result; + return { + address: result.formatted_address, + province: result.addressComponent.province, + city: result.addressComponent.city, + district: result.addressComponent.district, + street: result.addressComponent.street, + streetNumber: result.addressComponent.street_number, + }; + } else { + return { + address: '获取地址失败', + province: '', + city: '', + district: '', + street: '', + streetNumber: '', + }; + } + } catch (error) { + console.error('获取地址异常:', error); + throw error; + } + }, + + // 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); + return { + lat: lats, + lng: lngs, + }; + }, + + // 百度坐标转腾讯坐标 + baiduToGcj02(lat, lng) { + const x_pi = (3.14159265358979324 * 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); + return { + lat: lats, + lng: lngs, + }; + }, + + // 初始化位置信息 + async initLocation() { + try { + // 获取地址信息 + const address = await this.getAddressFromLocation( + this.latitude, + this.longitude, + ); + if (!address || !address.address) { + return; + } + + // 更新当前位置信息 + 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); + } + }, + }, +}; +</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 diff --git a/plugins/baiduMap/bmap-wx.min.js b/plugins/baiduMap/bmap-wx.min.js new file mode 100644 index 0000000..3c1f503 --- /dev/null +++ b/plugins/baiduMap/bmap-wx.min.js @@ -0,0 +1,356 @@ +/** + * 百度地图微信小程序 SDK + */ + +'use strict'; +function _classCallCheck(t, a) { + if (!(t instanceof a)) throw new TypeError('Cannot call a class as a function'); +} +var _createClass = (function() { + function t(t, a) { + for (var e = 0; e < a.length; e++) { + var i = a[e]; + (i.enumerable = i.enumerable || !1), + (i.configurable = !0), + 'value' in i && (i.writable = !0), + Object.defineProperty(t, i.key, i); + } + } + return function(a, e, i) { + return e && t(a.prototype, e), i && t(a, i), a; + }; + })(), + BMapWX = (function() { + function t(a) { + _classCallCheck(this, t), (this.ak = a.ak); + } + return ( + _createClass(t, [ + { + key: 'getWXLocation', + value: function(t, a, e, i) { + (t = t || 'gcj02'), + (a = a || function() {}), + (e = e || function() {}), + (i = i || function() {}), + wx.getLocation({ type: t, success: a, fail: e, complete: i }); + }, + }, + { + key: 'search', + value: function(t) { + var a = this; + t = t || {}; + var e = { + query: t.query || '生活服务$美食&酒店', + scope: t.scope || 1, + filter: t.filter || '', + coord_type: t.coord_type || 2, + page_size: t.page_size || 10, + page_num: t.page_num || 0, + output: t.output || 'json', + ak: a.ak, + sn: t.sn || '', + timestamp: t.timestamp || '', + radius: t.radius || 2e3, + ret_coordtype: 'gcj02ll', + }, + i = { + iconPath: t.iconPath, + iconTapPath: t.iconTapPath, + width: t.width, + height: t.height, + alpha: t.alpha || 1, + success: t.success || function() {}, + fail: t.fail || function() {}, + }, + n = function(t) { + (e.location = t.latitude + ',' + t.longitude), + wx.request({ + url: 'https://api.map.baidu.com/place/v2/search', + data: e, + header: { 'content-type': 'application/json' }, + method: 'GET', + success: function(t) { + var a = t.data; + if (0 === a.status) { + var e = a.results, + n = {}; + (n.originalData = a), (n.wxMarkerData = []); + for (var s = 0; s < e.length; s++) + n.wxMarkerData[s] = { + id: s, + latitude: e[s].location.lat, + longitude: e[s].location.lng, + title: e[s].name, + iconPath: i.iconPath, + iconTapPath: i.iconTapPath, + address: e[s].address, + telephone: e[s].telephone, + alpha: i.alpha, + width: i.width, + height: i.height, + }; + i.success(n); + } else + i.fail({ errMsg: a.message, statusCode: a.status }); + }, + fail: function(t) { + i.fail(t); + }, + }); + }, + s = function(t) { + i.fail(t); + }, + o = function(t) {}; + if (t.location) { + var c = t.location.split(',')[1]; + n({ + errMsg: 'input location', + latitude: t.location.split(',')[0], + longitude: c, + }); + } else a.getWXLocation('gcj02', n, s, o); + }, + }, + { + key: 'suggestion', + value: function(t) { + var a = this; + t = t || {}; + var e = { + query: t.query || '', + region: t.region || '全国', + city_limit: t.city_limit || !1, + output: t.output || 'json', + ak: a.ak, + sn: t.sn || '', + timestamp: t.timestamp || '', + ret_coordtype: 'gcj02ll', + }, + i = { + success: t.success || function() {}, + fail: t.fail || function() {}, + }; + wx.request({ + url: 'https://api.map.baidu.com/place/v2/suggestion', + data: e, + header: { 'content-type': 'application/json' }, + method: 'GET', + success: function(t) { + var a = t.data; + 0 === a.status + ? i.success(a) + : i.fail({ errMsg: a.message, statusCode: a.status }); + }, + fail: function(t) { + i.fail(t); + }, + }); + }, + }, + { + key: 'regeocoding', + value: function(t) { + var a = this; + t = t || {}; + var e = { + coordtype: t.coordtype || 'gcj02ll', + ret_coordtype: 'gcj02ll', + radius: t.radius || 1e3, + ak: a.ak, + sn: t.sn || '', + output: t.output || 'json', + callback: t.callback || function() {}, + extensions_poi: t.extensions_poi || 1, + extensions_road: t.extensions_road || !1, + extensions_town: t.extensions_town || !1, + language: t.language || 'zh-CN', + language_auto: t.language_auto || 0, + }, + i = { + iconPath: t.iconPath, + iconTapPath: t.iconTapPath, + width: t.width, + height: t.height, + alpha: t.alpha || 1, + success: t.success || function() {}, + fail: t.fail || function() {}, + }, + n = function(t) { + (e.location = t.latitude + ',' + t.longitude), + wx.request({ + url: 'https://api.map.baidu.com/reverse_geocoding/v3', + data: e, + header: { 'content-type': 'application/json' }, + method: 'GET', + success: function(a) { + var e = a.data; + if (0 === e.status) { + var n = e.result, + s = {}; + (s.originalData = e), + (s.wxMarkerData = []), + (s.wxMarkerData[0] = { + id: 0, + latitude: t.latitude, + longitude: t.longitude, + address: n.formatted_address, + iconPath: i.iconPath, + iconTapPath: i.iconTapPath, + desc: n.sematic_description, + business: n.business, + alpha: i.alpha, + width: i.width, + height: i.height, + }), + i.success(s); + } else + i.fail({ errMsg: e.message, statusCode: e.status }); + }, + fail: function(t) { + i.fail(t); + }, + }); + }, + s = function(t) { + i.fail(t); + }, + o = function(t) {}; + if (t.location) { + var c = t.location.split(',')[1]; + n({ + errMsg: 'input location', + latitude: t.location.split(',')[0], + longitude: c, + }); + } else a.getWXLocation('gcj02', n, s, o); + }, + }, + { + key: 'geocoding', + value: function(t) { + var a = this; + t = t || {}; + var e = { + address: t.address || '', + city: t.city || '', + ret_coordtype: t.coordtype || 'gcj02ll', + ak: a.ak, + sn: t.sn || '', + output: t.output || 'json', + callback: t.callback || function() {}, + }, + i = { + iconPath: t.iconPath, + iconTapPath: t.iconTapPath, + width: t.width, + height: t.height, + alpha: t.alpha || 1, + success: t.success || function() {}, + fail: t.fail || function() {}, + }; + if (t.address) + wx.request({ + url: 'https://api.map.baidu.com/geocoding/v3', + data: e, + header: { 'content-type': 'application/json' }, + method: 'GET', + success: function(t) { + var a = t.data; + if (0 === a.status) { + var e = a.result, + n = a; + (n.originalData = a), + (n.wxMarkerData = []), + (n.wxMarkerData[0] = { + id: 0, + latitude: e.location.lat, + longitude: e.location.lng, + iconPath: i.iconPath, + iconTapPath: i.iconTapPath, + alpha: i.alpha, + width: i.width, + height: i.height, + }), + i.success(n); + } else i.fail({ errMsg: a.message, statusCode: a.status }); + }, + fail: function(t) { + i.fail(t); + }, + }); + else { + var n = { errMsg: 'input address!' }; + i.fail(n); + } + }, + }, + { + key: 'weather', + value: function(t) { + var a = this; + t = t || {}; + var e = { + coord_type: t.coord_type || 'gcj02', + output: t.output || 'json', + ak: a.ak, + sn: t.sn || '', + timestamp: t.timestamp || '', + }, + i = { + success: t.success || function() {}, + fail: t.fail || function() {}, + }, + n = function(t) { + (e.location = t.longitude + ',' + t.latitude), + wx.request({ + url: 'https://api.map.baidu.com/telematics/v3/weather', + data: e, + header: { 'content-type': 'application/json' }, + method: 'GET', + success: function(t) { + var a = t.data; + if (0 === a.error && 'success' === a.status) { + var e = a.results, + n = {}; + (n.originalData = a), + (n.currentWeather = []), + (n.currentWeather[0] = { + currentCity: e[0].currentCity, + pm25: e[0].pm25, + date: e[0].weather_data[0].date, + temperature: + e[0].weather_data[0].temperature, + weatherDesc: e[0].weather_data[0].weather, + wind: e[0].weather_data[0].wind, + }), + i.success(n); + } else + i.fail({ errMsg: a.message, statusCode: a.status }); + }, + fail: function(t) { + i.fail(t); + }, + }); + }, + s = function(t) { + i.fail(t); + }, + o = function(t) {}; + if (t.location) { + var c = t.location.split(',')[0]; + n({ + errMsg: 'input location', + latitude: t.location.split(',')[1], + longitude: c, + }); + } else a.getWXLocation('gcj02', n, s, o); + }, + }, + ]), + t + ); + })(); +module.exports.BMapWX = BMapWX; diff --git a/plugins/baiduMap/config.js b/plugins/baiduMap/config.js new file mode 100644 index 0000000..cfddb5b --- /dev/null +++ b/plugins/baiduMap/config.js @@ -0,0 +1,13 @@ +/** + * 百度地图配置 + */ + +// 百度地图配置 +export const BAIDU_MAP = { + // 百度地图 ak Key + ak: 'ba7yaZ5vP6eM8hRu3x51NUsZ5myzkAmx', + // 百度地图 API 地址 + apiUrl: 'https://api.map.baidu.com', + // 坐标类型:bd09ll(百度经纬度坐标) + coordType: 'bd09ll', +}; diff --git a/plugins/baiduMap/index.js b/plugins/baiduMap/index.js new file mode 100644 index 0000000..4bff267 --- /dev/null +++ b/plugins/baiduMap/index.js @@ -0,0 +1,13 @@ +/** + * 百度地图插件入口文件 + */ + +// 引入百度地图 SDK +const { BMapWX } = require('./bmap-wx.min.js'); + +// 导入配置 +import { BAIDU_MAP } from './config'; + +// 导出组件、SDK 和配置 +import CBaiduMap from './CBaiduMap.weapp.vue'; +export { CBaiduMap, BMapWX, BAIDU_MAP }; -- Gitblit v1.9.1