uniapp+腾讯地图map 实现附近点吸附
思路
uniapp的map组件与腾讯地图微信小程序sdk均未提供点位吸附,因此思路为,通过地图拖动事件监听地图中心点,再计算该点与所有Markers点的距离,获取距离最短的marker对象,然后将地图中心设置为该marker即可
uniapp Map:
https://uniapp.dcloud.net.cn/component/map.html#map
腾讯地图微信小程序SDK
https://lbs.qq.com/miniProgram/jsSdk/jsSdkGuide/jsSdkOverview
效果:

下载sdk并引入

import QQMapWX from '@/static/qqmap/qqmap-wx-jssdk.min.js'
初始化map对象
this.qqmap = new QQMapWX({ key: ‘yourKey’ });
初始化markers,过程省略,markers参数格式见官方文档https://uniapp.dcloud.net.cn/component/map.html#marker
this.markers = [{ customCallout: { anchorX: -10 anchorY: 10 display: "ALWAYS" }, callout { anchorX: 0 anchorY: -10 bgColor: "#FFFFFF" borderColor: "#198DFF" borderRadius: "10" borderWidth: 10 content: "xxxxx" display: "BYCLICK" fontSize: 15 } height: "30px" iconPath: "../icon.png" id: 0 latitude: "19.982247" longitude: "110.343734" name: "xxxxx" width: "30px" }, { customCallout: {...}, callout {...} height: "30px" iconPath: "../icon.png" id: 0 latitude: "19.982247" longitude: "110.343734" name: "xxxxx" width: "30px" }, ...... ......]
渲染地图并添加移动监视
<map class="map" :markers="markers" :scale="13" :latitude="centerLat" :longitude="centerLng" :show-location="true" id="map" ref="map" @markertap="markertap" @regionchange="changeRegiion" @end="functionName" @begin="functionName" >
注:map组件的regionchange 事件直接在组件上写成 @regionchange,同时这个事件也非常特殊,它的 event type 有 begin 和 end 两个,导致我们无法在handleProxy 中区分到底是什么事件,所以你在监听此类事件的时候同时监听事件名和事件类型既 <map @regionchange="functionName" @end="functionName" @begin="functionName"><map>
"centerLat、centerLng"为当前的中心点坐标
监听地图中心点移动,重新设置中心点到距离最近的点
注:仅在事件为拖动(drag)和拖动结束(end)时执行
changeRegiion(e) { if (e.type == 'end' && e.causedBy == 'drag') { let point = { latitude: e.detail.centerLocation.latitude, longitude: e.detail.centerLocation.longitude, } let _self = this; let distanceList = [] //1.计算中心离每个点的距离 let vmarkers = _self.markers vmarkers.forEach((item, index, ) => { let distance = _self.calculateDistance(item.latitude, item.longitude, point.latitude, point .longitude); distanceList.push({ name: item.name, index: item.id, distance: distance }) }) //2.找出距离最近的点 let sortedList = distanceList.sort((a, b) => a.distance - b.distance) //3.重新设置中心点到该点 let markerIndex = sortedList[0].index; _self.centerLng = _self.markers[markerIndex].longitude; _self.centerLat = _self.markers[markerIndex].latitude; } }
计算两个经纬度之间的距离函数:
//计算两个经纬度距离 calculateDistance(lat1, lon1, lat2, lon2) { const radians = Math.PI / 180; const R = 6371; // 地球半径,单位为千米 const deltaLat = (lat2 - lat1) * radians; const deltaLon = (lon2 - lon1) * radians; lat1 = lat1 * radians; lat2 = lat2 * radians; const a = Math.sin(deltaLat / 2) * Math.sin(deltaLat / 2) + Math.cos(lat1) * Math.cos(lat2) * Math.sin(deltaLon / 2) * Math.sin(deltaLon / 2); const c = 2 * Math.atan2(Math.sqrt(a), Math.sqrt(1 - a)); const distance = R * c; return distance; }
PS:上面这样写的话,是不论移动到多远,都会有一个最近的点,即没有一个吸附距离的设置,如果需要设置吸附距离(距离小于多少才吸附),在计算完毕的距离列表中筛选即可,以2公里为例:
//小于2公里
if(sortedList[0].distance<=2){ _self.centerLng = _self.markers[markerIndex].longitude; _self.centerLat = _self.markers[markerIndex].latitude; _self.changeSelectStr(markerIndex); }
完整的:
changeRegiion(e) { if (e.type == 'end' && e.causedBy == 'drag') { let point = { latitude: e.detail.centerLocation.latitude, longitude: e.detail.centerLocation.longitude, } let _self = this; let distanceList = [] //1.计算中心离每个点的距离 let vmarkers = _self.markers vmarkers.forEach((item, index, ) => { let distance = _self.calculateDistance(item.latitude, item.longitude, point.latitude, point .longitude); distanceList.push({ name: item.name, index: item.id, distance: distance }) }) //2.找出距离最近的点 let sortedList = distanceList.sort((a, b) => a.distance - b.distance) //3.重新设置中心点到该点(小于2公里时) if(sortedList[0].distance<=2){ _self.centerLng = _self.markers[markerIndex].longitude; _self.centerLat = _self.markers[markerIndex].latitude; _self.changeSelectStr(markerIndex); } } }
完毕

浙公网安备 33010602011771号