百度地图点聚合MarkerClusterer性能优化

公司要求做个百度地图点聚合的性能优化,需一次性加载9万条数据。

记录下自己的优化过程。(只想看优化代码的可直接移步:步骤三)

一、引入百度地图

  • vue项目中,在index.html文件中用script标签引入百度地图(ak=秘钥)
<script type="text/javascript" src="http://api.map.baidu.com/api?v=3.0&ak=6BUBoNWirHMQajt9f2hzWF1mDK7MsR8n"></script>
  • 并初始化地图
    initMap() {
      this.map = new BMap.Map('map_layer', {mapType: BMAP_HYBRID_MAP});
      this.map.centerAndZoom(new BMap.Point(116.404, 39.915), 5);
      this.map.enableScrollWheelZoom(true);
    },

二、在页面的头部应用点聚合工具开源库的文件

  vue项目,可在index.html中用script标签引入

  <script type="text/javascript" src="http://api.map.baidu.com/library/MarkerClusterer/1.2/src/MarkerClusterer_min.js"></script>
  <script type="text/javascript" src="./static/MarkerClusterer.js"></script>

 

三、点聚合优化,参考博客1 + 参考博客2

  百度的点聚合算法 是基于方格和距离的聚合算法,即开始的时候地图上没有任何已知的聚合点,然后遍历所有的点,去计算点的外包正方形(由gridSize指定),若此点的外包正方形与现有的聚合点的外包正方形不相交,则新建聚合点,若相交就把该点加到该聚合点,效果如下图。

  应用百度地图源码,超过2000点,就卡顿的无法使用了。于是对源码进行优化。

  百度地图中的点聚合主要有两个文件,一个控制聚合即MarkerClusterer.js,一个控制显示的样子TextIconOverlay.js,(这里吐槽一下,官方给的文档并没有说明!!!)

http://api.map.baidu.com/library/TextIconOverlay/1.2/src/TextIconOverlay_min.js(无格式压缩版)

http://api.map.baidu.com/library/TextIconOverlay/1.2/src/TextIconOverlay.js

http://api.map.baidu.com/library/MarkerClusterer/1.2/src/MarkerClusterer_min.js(无格式压缩版)

http://api.map.baidu.com/library/MarkerClusterer/1.2/src/MarkerClusterer.js


 百度地图源码解析,可参考博客

 这里展示百度地图MarkerClusterer.js的部分源码,用以说明优化的原理。

/**
     * 根据所给定的标记,创建聚合点
     * @return 无返回值
     */
    MarkerClusterer.prototype._createClusters = function(){
        var mapBounds = this._map.getBounds();
        var extendedBounds = getExtendedBounds(this._map, mapBounds, this._gridSize);
        for(var i = 0, marker; marker = this._markers[i]; i++){
            if(!marker.isInCluster && extendedBounds.containsPoint(marker.getPosition()) ){ 
                this._addToClosestCluster(marker);
            }
        }   
    };

    /**
     * 根据标记的位置,把它添加到最近的聚合中
     * @param {BMap.Marker} marker 要进行聚合的单个标记
     *
     * @return 无返回值。
     */
    MarkerClusterer.prototype._addToClosestCluster = function (marker){
        var distance = 4000000;
        var clusterToAddTo = null;
        var position = marker.getPosition();
        for(var i = 0, cluster; cluster = this._clusters[i]; i++){
            var center = cluster.getCenter();
            if(center){
                var d = this._map.getDistance(center, marker.getPosition());
                if(d < distance){
                    distance = d;
                    clusterToAddTo = cluster;
                }
            }
        }
    
        if (clusterToAddTo && clusterToAddTo.isMarkerInClusterBounds(marker)){
            clusterToAddTo.addMarker(marker);
        } else {
            var cluster = new Cluster(this);
            cluster.addMarker(marker);            
            this._clusters.push(cluster);
        }    
    };
View Code

以上两个方法就是前文所述的算法的具体实现,

先排除所有不在可视范围的点,然后通过比较marker点和聚合点的距离,拿到距离最近的聚合点,判断marker点是否在聚合点的外包正方形内;

这一段是正常算法需要没啥问题,看起来问题只能出在  cluster.addMarker(marker)了

if(this.isMarkerInCluster(marker)){
            return false;
        }//也可用marker.isInCluster判断,外面判断OK,这里基本不会命中
    
        if (!this._center){
            this._center = marker.getPosition();
            this.updateGridBounds();//
        } else {
            if(this._isAverageCenter){
                var l = this._markers.length + 1;
                var lat = (this._center.lat * (l - 1) + marker.getPosition().lat) / l;
                var lng = (this._center.lng * (l - 1) + marker.getPosition().lng) / l;
                this._center = new BMap.Point(lng, lat);
                this.updateGridBounds();
            }//计算新的Center
        }
    
        marker.isInCluster = true;
        this._markers.push(marker);
    
        var len = this._markers.length;
        if(len < this._minClusterSize ){     
            this._map.addOverlay(marker);
            //this.updateClusterMarker();
            return true;
        } else if (len 
  • 0
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值