likes
comments
collection
share

🔥浅地图点聚合——适用于所有地图前言📌 产品 : 地图这标点一多密密麻麻的的我怎么看啊! 随后拿出其他的产品和我说

作者站长头像
站长
· 阅读数 17

📌 前言

  • 产品 : 地图这标点一多密密麻麻的的我怎么看啊! 随后拿出其他的产品和我说 , 我要实现这个效果 。
  • 我 : 这个叫点聚合 , 我研究一下吧!
  • 第二天
  • 我 : 写不出来 , 不好兼容AndroidIOS , 而且不知道为什么我代码不生效 , 没反应 。
  • 产品 : 那别人写的出 , 你写不出 , 不就是你技术不行 。
  • 我 : 一分钱一分货 , 我这四舍五入等于零的工资 , 给你写地图都不错了 。

备注:公司内部人员自己使用的项目 , 项目使用的技术是uniapp , 地图这块使用的是自带的组件map

被嘲讽之后 , 我开始想办法从另一种方法去实现这个功能 , 毕竟这点密密麻麻的确实不应该这样 , 也确实是我没写出来点聚合。

💡 解决方案

点聚合 , 说白了就是当一堆点聚在一起时变成一个数字 , 不要死堆积在一起 , 影响体验和感官 。

而我拿到的数据就是一串带有坐标的数组 , 随后在地图上进行标点 。

看着我手机上坐在一起吃年夜饭的坐标 , 我开始了00后的奇思妙想 , 那我能不能把这一堆挤在一起的点变成一个点呢 , 名字就带有数字??

思考到这里 , 主要架构已经出来了 。

拿到所有坐标的经纬度 , 在平面上是二维坐标系 , 根据勾股定理判断两点之间的距离 , 再根据地图缩放度判断标点是否重合 , 如果重合创建新的标记点为两点直线的中心, 标点名称图标更改 , 接下来删除重合的两点 , 最后进行算法递归得到全新的数组

  • 产品 : 说人话
  • 我: ...就是点重合变成新的点 , 名字叫这里有XX位客户

效果图

🔥浅地图点聚合——适用于所有地图前言📌 产品 : 地图这标点一多密密麻麻的的我怎么看啊! 随后拿出其他的产品和我说

🥰 编码实现

注意自己的项目是修改部分代码的 , 直接粘贴不能使用哦!

/**
 * 注意 需要监听地图缩放度
 * res.scale 地图缩放度实时改变
 * this.scale 保存上次的缩放值
 * this.initMarkers 接口拿到的所有标记点
 */ 
this.mapContext.getScale({
    success:(res) => {
        // 缩放带有小数点 , 我们只考虑整数
        let scale = parseInt(res.scale) 
        // 缩放未改变 , 不需要重新渲染
        if (this.scale==scale) {
                return
        }
        // 缩放改变 , 记录缩放值
        this.scale = scale
        // 初始标记点数组 , 深拷贝 , 防止初始数据被破坏
        const initMarkers = [...this.initMarkers]
        // 新标记点数组
        let newMarkers = []
        // 临时标记点 , 后续添加进新数组中
        let maker = ""
        /**
         * 合成标记点方案 , 地图缩放范围[0,20] , 
         * 这里记录在每个范围要合成的距离 , 前3个没给因为我这里限制范围为[3,20]
         */
        let compoundDistance = [
            1,2,3,81536,40768,20384,10192,5096,2048,1024,
            512,256,128,64,32,16,8,4,2,0
        ][scale]
        /**
         * 新数组递归赋值——内部函数
         * IterativeMarkerPoint 对比合并坐标点数组
         */
        const assignmentIteration = (IterativeMarkerPoint)=>{
            // 临时标记点赋值
            maker = {...IterativeMarkerPoint[0]}
            // 对比数组去除标记点
            IterativeMarkerPoint = IterativeMarkerPoint.slice(1)
            // 已分配标记点下标记录
            const recordIndex = []
            // 开启对比合并
            IterativeMarkerPoint.forEach((item,index)=>{
                let X = (maker.longitude - item.longitude) * (maker.longitude - item.longitude)
                let Y = (maker.latitude - item.latitude) * (maker.latitude - item.latitude)
                // 两点之间的坐标距离(数字太小*10000以做比对)
                let distance =  Math.sqrt(X + Y) * 10000
                // 距离太近合并  
                if (distance < compoundDistance) {
                    // 记录合并下标
                    recordIndex.push(index)
                    // 临时标记点修改
                    maker = {
                        ...maker,
                        id:-1,
                        longitude: (Number(maker.longitude) + Number(item.longitude)) / 2,
                        latitude: (Number(maker.latitude)  +Number(item.latitude)) / 2,
                        iconPath:AggregationPoint,
                        label:{
                            content:'这里有'+(recordIndex.length + 1)+ '位客户',
                        }
                    }
                }
            })
            // 去除刚刚合并的标点
            IterativeMarkerPoint=IterativeMarkerPoint.filter((item,index)=>!recordIndex.includes(index))
            // 将合成的临时新标记点添加新标点数组
            newMarkers.push(maker)
            // 还有未分配标记点 , 递归执行函数
            if (IterativeMarkerPoint.length!==0) {
                assignmentIteration(IterativeMarkerPoint)
            }
        }
        // 开始执行递归函数
        assignmentIteration(initMarkers)  
        // 这里就是将新函数标点进地图 , PC的地图需要删除旧标点添加新标点
        // 我这边this.markers就是标点 , 响应式的
        this.markers = newMarkers
    }
})		

小公司 , 命名不是很规范 , 非常抱歉

📚 写在最后

逻辑都是这个逻辑 , 可以适用所有的地图标点 , 毕竟只是重新构造了一份标点 。

如果有需要沟通交流的可以私信博主 , 欢迎评论 。

感谢阅读 , 立正 !!!

转载自:https://juejin.cn/post/7404036819108282387
评论
请登录