高德地图的开发实践

1.大量点标记的处理(点聚合||海量点)

普通点标记 Marker 是一个个 dom,当 Marker 太多时内存占用过高,页面会卡顿,可采用两种优化方案:

  • 点聚合:设置 gridSize,相邻点进行聚合,减少 dom 数

示例:点聚合-点标记-示例中心-JS API 示例 | 高德地图API

// 聚合渲染
    renderCluster() {
      this.curVisibleType.map(type => {
        this.dataMap[type].map(item => {
          const marker = new AMap.Marker({
            offset: new AMap.Pixel(this.markerOffset.x, this.markerOffset.y),
            extData: { ...item, type },
            position: item.position,
            content: this.setCabinet(this.typeMap[type], item.hasCount)
          });
          marker.on("click", this.handleMarkerClick);
          this[`markers${type}`].push(marker);
        });
​
        this[`cluster${type}`] = new AMap.MarkerClusterer(
          this.mapInst,
          this[`markers${type}`],
          {
            gridSize: 80,
            maxZoom: 18,
            renderClusterMarker: ({ count, marker, markers }) => {
              this.customClusterMarker({ count, marker, markers }, type);
            }
          }
        );
      });
    }
  • 海量点:将同类点绘制到一个 canvas 图层里,提升性能,解决卡顿

注意 :海量点图层的创建、显隐、事件、自定义样式是否能达到需求效果

//创建海量点柜机图层
    createMassMarks(index, data, type) {
      let styleObjectArr = [
        {
          size: new AMap.Size(24, 24), // 图标大小
          anchor: new AMap.Pixel(12, 12), // 图标显示位置偏移量,基准点为图标中心
          url: require('@/assets/img/siteSel/usual-cabinet.svg')
        }, //不动
        {
          size: new AMap.Size(24, 24),
          anchor: new AMap.Pixel(12, 12),
          url: require('@/assets/img/siteSel/add-cabinet.svg')
        }, //扩容
        {
          size: new AMap.Size(24, 24),
          anchor: new AMap.Pixel(12, 12),
          url: require('@/assets/img/siteSel/sub-cabinet.svg')
        }, //缩容
        {
          size: new AMap.Size(24, 24),
          anchor: new AMap.Pixel(12, 12),
          url: require('@/assets/img/siteSel/zero-cabinet.svg')
        }, //0周转
        {
          size: new AMap.Size(20, 20),
          anchor: new AMap.Pixel(10, 10),
          url: require('@/assets/img/siteSel/nerveCabinet.svg')
        } //最优普通||图神经普通
      ];
      let massMarksList = new AMap.MassMarks(data, {
        cursor: 'pointer',
        style: styleObjectArr,
        zIndex: index, // 海量点图层叠加的顺序
        zooms: [3, 19] // 在指定地图缩放级别范围内展示海量点图层
      });
    }

效果图:

2.大量 polyline 时的处理

当地图内的 polyline 太多时,内存占用过高,页面会卡顿

解决思路:三重过滤数据:只加载可视区内的边->过滤太短的边->根据缩放等级确定加载量 缩放等级太低时加载少量边

let tmapBounds = this.mapInst.getBounds();
let southWest = new AMap.LngLat(
  tmapBounds.southwest.lng,
  tmapBounds.southwest.lat
);
let northEast = new AMap.LngLat(
  tmapBounds.northeast.lng,
  tmapBounds.northeast.lat
);
​
//绘制地图可视区域
let bounds = new AMap.Bounds(southWest, northEast);
this.rectangle = new AMap.Rectangle({
  bounds: bounds,
  strokeColor: "red",
  strokeWeight: 6,
  strokeOpacity: 0,
  strokeStyle: "dashed",
  fillColor: "blue",
  fillOpacity: 0,
  cursor: "pointer",
  zIndex: 50,
  bubble: true,
});
this.rectangle.setMap(this.mapInst);
​
type == 0 &&
  (ary = ary.filter(
    (item) =>
      this.rectangle.contains(item.originPosition) ||
      this.rectangle.contains(item.endPosition)
  )); //短物理边 两个端点在可视区内即加载
​
type == 1 &&
  (ary = ary.filter(
    (item) =>
      this.rectangle.contains(item.originPosition) ||
      this.rectangle.contains(item.endPosition) ||
      AMap.GeometryUtil.doesSegmentRingIntersect(
        item.originPosition,
        item.endPosition,
        [
          southWest,
          northEast,
          [southWest.lng, northEast.lat],
          [northEast.lat, southWest.lng],
        ]
      )
  )); //长频次边 两个端点在可视区内 或者 边与可视区交叉即加载
  • 过滤短边

ary = ary.filter(item => this.calculateSideLength(item.originPosition, item.endPosition) > filterLength)
​
calculateSideLength(originPosition, endPosition) {
//计算边长度
      let originLnglat = new AMap.LngLat(originPosition[0], originPosition[1]);
      let originPixel = this.mapInst.lngLatToContainer(originLnglat);
​
      let endLnglat = new AMap.LngLat(endPosition[0], endPosition[1]);
      let endPixel = this.mapInst.lngLatToContainer(endLnglat);
​
      let length = Math.sqrt(Math.pow(originPixel.x - endPixel.x, 2) + Math.pow(originPixel.y - endPixel.y, 2));
​
      return length;
 }
  • 根据缩放等级过滤

let num = zoom >= 17 ? ary.length : ary.length > baseNum ? baseNum : ary.length;
​
[type == 0 || (type == 1 && zoom <= 13)] && (ary = ary.splice(0, num));

效果图:

3.地理围栏为环多边形或多多边形时的处理

问题:某个区域有多个多边形块时,只有第一个块可点击 hover;

解决思路:

1.对于多个多边形块应循环数组直接绘制,对于环多边形,应建立二维数组

2.区分多多边形和环多边形:

  • 获取最大多边形块的 path 数组和除最大多边形块的其他多边形块 path 数组;

  • 遍历除最大多边形块的其他多边形块 path 数组,包含在最大多边形块里则为环多边形, 否则为多多边形

效果图:

 

 //地理围栏绘制和清除
    gridShow() {
      this.polygonList.length !== 0 && this.mapInst.remove(this.polygonList);
      if (this.gridActive) {
        this.polygonList = [];
        this.edList.map(item => {
          if (item.polygonNum == 1) {
            const polygon = this.createPolygon(item, item.polygonList);
            this.handlePolygon(polygon);
          } else {
            //某个区域有多个多边形块时 (解决多个多边形块只有第一个块可点击 hover的问题)
            let lengthAry = [];
            item.polygonList.map(item => {
              lengthAry.push(item.length);
            });
            let maxLength = Math.max(...lengthAry);
            let maxPolygonAry = item.polygonList.filter(item => item.length == maxLength); //最大多边形块的path数组
            let otherPolygonAry = item.polygonList.filter(item => item.length !== maxLength); //除最大多边形块的其他多边形块path数组
​
            const maxPolygon = this.createPolygon(item, maxPolygonAry); //最大多边形块
​
            otherPolygonAry.map(items => {
              if (maxPolygon.contains(items[0])) {
                //如果其他多边形块的点包含在最大多边形块里,说明 为环多边形 建立二维数组
                maxPolygonAry[maxPolygonAry.length] = items;
              } else {
                //如果其他多边形块的点不包含在最大多边形块里,则直接绘制多边形块
                const polygon = this.createPolygon(item, items);
                this.handlePolygon(polygon);
              }
            });
            //绘制最终的最大多边形块 清除初始最大多边形块
            const maxPolygonEnd = this.createPolygon(item, maxPolygonAry);
            this.mapInst.remove(maxPolygon);
            this.handlePolygon(maxPolygonEnd);
          }
        });
      } else {
        this.polygonList.length !== 0 && this.mapInst.remove(this.polygonList);
      }
    }

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值