leaflet + vue 海量点位批量显示,根据不同缩放级别显示不同数量的点位

     最近在项目中遇到一个需求,以前点位是根据区县进行分组聚合式显示的,但是交互不够友好直接,需要不断地点开才行,因此产品要求把所有点位平铺显示,不要分组,根据不同的缩放级别显示不同数量的点位。咨询了同事,给出这样一个方案:

     定义一个新数组,循环所有点位,先把点位的经纬度转换成屏幕的坐标(用到 leaflet 的 latLngToContainerPoint 方法),然后计算该点位和新数组里所有点的距离(勾股定理),大于某个距离(比如50px)就push进新数组,然后在地图上显示新数组的点位,这样点位就不会全部密密麻麻的显示在地图上了,而是每个点之间都有一定的距离。

    因为循环次数比较多,为了提高渲染速度,做了以下处理:

    1. 首先增加一个判断条件,只渲染地图可视范围内的点位,不在可视范围内的点直接退出循环

    2. 尽量不要在循环体中去访问 this,很耗费时间,把所有可以保存成变量的都放在外面定义好,直接拿去循环里用

    效果如下:

 

 

 核心代码如下:

 1 createPointsByZoom(key) {
 2       // 放大到 14 级别以上,展示所有的点位
 3       if (this.map.getZoom() > 14) {
 4         this.staData.push(...this.points[key])
 5         return
 6       }
 7 
 8       const TARGET_DISTANCE = 50 // 两点之间的距离:50px
 9       const zoom = this.map.getZoom()
10       const newList = [this.points[0]] // this.points 是指所有点位,默认放入一个点位
11       const bounds = this.map.getBounds() // 地图边界
12       const lat1 = bounds._southWest.lat
13       const lat2 = bounds._northEast.lat
14       const lon1 = bounds._southWest.lng
15       const lon2 = bounds._northEast.lng
16 
17       this.points.map(item => {
18         const { latitude, longitude } = item
19 
20         // 只画可视范围内的
21         if (!this.isInView(lat1, lat2, lon1, lon2, latitude, longitude)) {
22           return
23         }
24 
25         const latLng1 = L.latLng([latitude, longitude])
26         const location1 = this.map.latLngToContainerPoint(latLng1, zoom) // { x: 123, y: 123 }
27         const { x, y } = location1
28 
29         /**
30          * 比较每一个点和容器中的点的距离
31          * latLngToContainerPoint: 将经纬度转换为相对地图容器的屏幕坐标
32          */
33         const moreThanStandardDistance = newList.every(data => {
34           const latLng2 = L.latLng([data.latitude, data.longitude])
35           const location2 = this.map.latLngToContainerPoint(latLng2, zoom)
36           // 计算两点之间的屏幕距离, 勾股定理
37           const distanceX = Math.abs(x - location2.x)
38           const distanceY = Math.abs(y - location2.y)
39           const distance = Math.pow(distanceX, 2) + Math.pow(distanceY, 2)
40           return distance > Math.pow(TARGET_DISTANCE, 2)
41         })
42 
43         if (moreThanStandardDistance) {
44           newList.push(item)
45         }
46       })
47 
48       this.staData.push(...newList)
49     }

 

posted @ 2022-10-26 10:14  我就尝一口  阅读(1442)  评论(0编辑  收藏  举报