🔥浅地图点聚合——适用于所有地图前言📌 产品 : 地图这标点一多密密麻麻的的我怎么看啊! 随后拿出其他的产品和我说
📌 前言
- 产品 : 地图这标点一多密密麻麻的的我怎么看啊! 随后拿出其他的产品和我说 , 我要实现这个效果 。
- 我 : 这个叫点聚合 , 我研究一下吧!
- 第二天
- 我 : 写不出来 , 不好兼容
Android
和IOS
, 而且不知道为什么我代码不生效 , 没反应 。 - 产品 : 那别人写的出 , 你写不出 , 不就是你技术不行 。
- 我 : 一分钱一分货 , 我这四舍五入等于零的工资 , 给你写地图都不错了 。
备注:公司内部人员自己使用的项目 , 项目使用的技术是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