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);
                    }
 } }

完毕

 

posted @ 2025-05-30 17:23  陈鹏昱Chen  阅读(80)  评论(0)    收藏  举报