vue中高德地图使用 Marker 标点 - 标点数据快到 1000 时页面卡顿问题解决(已解决 - 多方面原因)+ 海量点功能实现解决

17 篇文章 0 订阅
6 篇文章 0 订阅

1.业务需求

需要在 高德地图 中标点,标点数量可能 上万个

2.最初实现及出现的问题

  • 【最初实现】使用高德地图的 Marker 标点
    • Marker 实现标点代码
      // 遍历list数据一个一个标点
      let warnning = new AMap.Marker({
        zIndex: type === 'alarm' ? 14 : 12,
        icon: icon,
        position: [item.longitude, item.latitude],
        anchor: 'bottom-center',
        extData: {
          tabType: type,
          ...item
        }
      })
      this.markerList.push(warnning) // 用于
      warnning.on('click', this.markerClick)
      // warnning.emit('click', { target: warnning });//
      map.add(warnning)
      
  • 【问题】1000 个标点时页面就出现 卡顿

3.解决 - 1000 个标点时页面就出现 卡顿 问题

想尽各种办法:

  1. 【海量点第一种方法】:海量点 MassMarks 官方示例 (代码示例如下)
  2. 【海量点第二种方法】:标注和标注图层-海量点 官方示例
  3. 【点聚合】:MarkerCluster 官方示例

【海量点第一种方法】代码

<script>
/* 注释掉的代码与当前功能无关 */
let map = null
// let infoWindowCon = null
// let contextMenu = null
let makerPeak = null

export default {
  name: 'mapManager',
  data() {
    return {
      // ...
      dangerSucMass: null // 【关键代码】海量点图层
    }
  },
  methods: {
    // 使用【海量点第一种方法】实现标点
    completeAddMarker(data) {
      this.dangerSucMass?.clear()
      const list = (data || []).map((item, index) => {
        return {
          id: item.id,
          name: item.address,
          lnglat: [item.longitude, item.latitude],
          style: 0,
          extData: {
            tabType: 'dangerSuceess',
            ...item
          }
        }
      })
      this.dangerSucMass = new AMap.MassMarks(list, {
        opacity: 0.8,
        zIndex: 111,
        cursor: 'pointer',
        style: [{
          url: require('@/assets/image/green.png'),
          anchor: AMap.Pixel(0, 0),
          size: new AMap.Size(10, 10),
          zIndex: 3
        }]
      })
      this.dangerSucMass.setMap(map)

      this.dangerSucMass.on('click', this.successMarkerClick)
    },
    // 展示/隐藏图标
    isShowSucMass(e) {
      if (e) {
        this.dangerSucMass.show()
        this.markerTip.open(map)
      } else {
        this.dangerSucMass.hide()
        this.markerTip.close()
      }
    },
    //监听
    successMarkerClick(e) {
      console.log('e--successMarkerClick--打印', e)
      // 添加点击marker时的提示
      if (this.markerTip) {
        this.markerTip.close() // 关闭提示
      }
      const data = e.data.extData
      console.log('e.data.extData----打印', data)
      this.infoWindowData = { ...data, type: 'dangerSuceess' }
      const position = [data.longitude, data.latitude]
      map.setCenter(new AMap.LngLat(position[0], position[1]), true)
      this.markerTip = new AMap.InfoWindow({ // 提示插件
        position: new AMap.LngLat(position[0], position[1]), // 经纬度
        content: this.$refs['infoW'].$el,
        offset: new AMap.Pixel(5, 0) // 偏移位置
      })
      this.markerTip.open(map)
      // this.$refs.infoW.open({...e.data.extData, typeTab: 'dangerSuceess'})
    },
  }
}
</script>

4.使用海量点、聚合标点后还有卡顿,排查其他原因

以上三种办法 - 页面还是卡顿 - 基于以上三种解决办法排查到以下多方面原因:

  1. 页面中有list数据 列表渲染,数据过多,页面数据渲染过多也会导致页面卡顿
  2. 地图相关的变量data 中声明(此处以【海量点第一种方法】为例)
    • 以上 【海量点第一种方法】代码 中可以看到,海量点实例 dangerSucMassdata 中声明 ↓↓↓
    • 所有 地图相关的实例不要放在 vue 的可响应数据中,响应数据会 劫持属性地图的属性会被修改,另外,劫持的属性可能和渲染有关,那么 会增加很多响应的计算,会很卡; 参考别人遇到的类似的问题-官方解释
      在这里插入图片描述

5.最终解决

5.1页面中list数据渲染问题解决

最初地图标点和list数据使用的是一套数据
【解决】

  • 地图标点数据页面渲染数据 分成两套列表数据
    • 地图标点数据:获取所有标点数据
    • 页面渲染数据列表:改成分页获取数据,单次获取一部分数据

5.2地图相关实例不要放在 vue 的可响应数据中

最终解决办法【海量点第一种方法】代码

<script>
/* 注释掉的代码与当前功能无关 */
let map = null
// let infoWindowCon = null
// let contextMenu = null
let makerPeak = null
let dangerSucMass = null // 【关键代码】【解决代码】海量点实例 - 不在 data 中

export default {
  name: 'mapManager',
  data() {
    return {
      // ...
      // dangerSucMass: null // 【关键代码】海量点实例
    }
  },
  methods: {
    // 使用【海量点第一种方法】实现标点
    completeAddMarker(data) {
      dangerSucMass?.clear()
      const list = (data || []).map((item, index) => {
        return {
          id: item.id,
          name: item.address,
          lnglat: [item.longitude, item.latitude],
          style: 0,
          extData: {
            tabType: 'dangerSuceess',
            ...item
          }
        }
      })
      dangerSucMass = new AMap.MassMarks(list, {
        opacity: 0.8,
        zIndex: 111,
        cursor: 'pointer',
        style: [{
          url: require('@/assets/image/green.png'),
          anchor: AMap.Pixel(0, 0),
          size: new AMap.Size(10, 10),
          zIndex: 3
        }]
      })
      dangerSucMass.setMap(map)

      dangerSucMass.on('click', this.successMarkerClick)
    },
    // 展示/隐藏图标
    isShowSucMass(e) {
      if (e) {
        dangerSucMass.show()
        this.markerTip.open(map)
      } else {
        dangerSucMass.hide()
        this.markerTip.close()
      }
    },
    //监听
    successMarkerClick(e) {
      console.log('e--successMarkerClick--打印', e)
      // 添加点击marker时的提示
      if (this.markerTip) {
        this.markerTip.close() // 关闭提示
      }
      const data = e.data.extData
      console.log('e.data.extData----打印', data)
      this.infoWindowData = { ...data, type: 'dangerSuceess' }
      const position = [data.longitude, data.latitude]
      map.setCenter(new AMap.LngLat(position[0], position[1]), true)
      this.markerTip = new AMap.InfoWindow({ // 提示插件
        position: new AMap.LngLat(position[0], position[1]), // 经纬度
        content: this.$refs['infoW'].$el,
        offset: new AMap.Pixel(5, 0) // 偏移位置
      })
      this.markerTip.open(map)
      // this.$refs.infoW.open({...e.data.extData, typeTab: 'dangerSuceess'})
    },
  }
}
</script>

页面展示

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值