在vue项目中使用高德地图MassMarks

3,481 阅读2分钟

海量标点,官方文档说,10万以下数据性能都可以很好。实际项目中,真实数据最多7千。自测5万左右的数据性能都是挺好的(坐标转换前)。

一、引入高德地图

通过vue-amap引入,npm安装:

import VueAMap from 'vue-amap';

Vue.use(VueAMap);
VueAMap.initAMapApiLoader({
  key: 'YOUR_KEY',
  plugin: ['AMap.Scale', 'AMap.OverView', 'AMap.ToolBar', 'AMap.MapType',...],
  v: '1.4.15'//默认1.4.4,改为1.4.15,因为版本低会导致海量标点的rotation属性无效
});

二、兼容高德原生SDK

import VueAMap from 'vue-amap'
import { lazyAMapApiLoaderInstance } from 'vue-amap'
const amapManager = new VueAMap.AMapManager()
export default{
  data(){
    return{
      massData:[],
      massStyle:[],
      mass:{},
      amapManager,
      events:{
        init(o){
          lazyAMapApiLoaderInstance.load().then(() => {
            ...
          })
        } 
      }  
    }
  },
  methods:{
    ...
  }
}

三、创建MassMarks类

在地图加载完后创建MassMarks实例

lazyAMapApiLoaderInstance.load().then(() => {
    //创建MassMarks类实例
    const massMarks = new AMap.MassMarks([], {
        zIndex: 1000,
        zooms: [12, 18],
        style: []
    })
    //将海量标点添加至地图实例
    massMarks.setMap(o)
    //添加点击事件
    massMarks.on('click', (e) => {
        console.log('e:',e)
    })
    // 将海量标点实例保存至全局
    this.mass = massMarks
})

四、在websocket中接收数据

onMessage(e) { // 数据接收
    const data = JSON.parse(e.data).data
    if (!data) { // 没有数据
        console.warn('websocket:', '未接收到小船数据')
        this.$message.warning({
          message: '未接收到小船数据',
          center: true
        })
        return
    }
    this.getMassData(data)
}

五、处理数据(转换坐标)

调用高德API转换坐标,若需要转换的坐标太多(自测一次性转换1300左右个坐标就会不成功),需要先切割数组,分多次转换后再合并。

getMassData(data){
    const dataArr = []    // 需转换的坐标数组
    const initData = []   // 海量标点数据
    const initStyle = []  // 海量标点样式
    for (let i = 0; i < data.length; i++) { 
        dataArr.push([data[i].longitude, data[i].latitude])
        initData.push({ lnglat: [], style: i, targetId: data[i].targetId })
        initStyle.push({
            url: require('@/assets/icon/boat2.svg'),
            size: new AMap.Size(19, 19),
            anchor: new AMap.Pixel(8, 8),
            rotation: data[i].course
        })
    }
    this.massData = initData
    this.massStyle = initStyle
    // 切割数组,每个1000
    for (let i = 0; i < dataArr.length; i += 1000) { 
        path.push(dataArr.slice(i, i + 1000))
    }
    //发起转换坐标请求
    const promises = path.map((item) => {
        return this.convertFrom(item, 'gps')
    })
    Promise.all(promises).then((res) => {
        const totalRes = res.reduce((total, item) => {
            if (item.info === 'ok') {
                return [...total, ...item.locations]
            } else {
                return total
            }
        }, [])
        console.log('转换后的坐标:',totalRes)
        ...
        this.creatMassMarkers(this.massData, this.massStyle)
    })
},
convertFrom(path, type) {
    return new Promise((resolve, reject) => {
        AMap.convertFrom(path, type, function(status, result) {
          if (result.info === 'ok') {
            resolve(result)
          }
        })
    })
}

六、给MassMarks类添加数据

methods:{
    //向MassMarks类添加数据和样式
    creatMassMarkers(data, style) {
        this.mass.setData(data)
        this.mass.setStyle(style)
    }
  }

七、链接自取

  1. MassMarks类-全部属性和方法
  2. 海量点标记-用法文档