精华内容
下载资源
问答
  • 百度地图点聚合

    2019-03-01 12:45:28
    百度地图点聚合的自定义文件,解决了大量点聚合加载卡的问题
  • 百度地图 点聚合

    2017-12-20 15:05:34
    百度地图点聚合可设置点聚合起始聚合点数量 mClusterManager.setMackSize(2);
  • 百度地图点聚合demo

    2017-03-13 14:59:08
    android 百度地图点聚合demo
  • 百度地图点聚合代码,配合csdn博客,提供给大家一起来参考!学习,如果有相关问题,可以一起交流! 百度地图点聚合相关代码
  • 百度地图点聚合需要导入的类百度地图点聚合需要导入的类从百度点聚合示例项目中拷出来的
  • 百度地图点聚合实现自定义样式。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。
  • 百度地图点聚合的聚合点样式修改

    千次阅读 2018-06-02 22:47:00
    百度地图点聚合的聚合点样式修改 学习了:https://blog.csdn.net/sut_haohaoxuexi/article/details/78542406 原文膜拜: 百度地图提供点聚合的功能,但是聚合之后的样式不一定会满足我们的需要: 点聚合会用到百度...

    百度地图点聚合的聚合点样式修改

    学习了:https://blog.csdn.net/sut_haohaoxuexi/article/details/78542406

    原文膜拜:

    百度地图提供点聚合的功能,但是聚合之后的样式不一定会满足我们的需要:
    
    点聚合会用到百度自己写的js文件,分别是MarkerClusterer.js,以及TextIconOverlay.js,其中MarkerClusterer.js是实现点的聚合,TextIconOverlay.js是设置聚合点的样式,
    
    在这里,需要修改TextIconOverlay.js这个文件,在TextIconOverlay.js中查看,_image_path就可以看到点聚合图片url,修改即可改变聚合点的样式。

     

    学习了:https://zhidao.baidu.com/question/1821895278618185908.html  源码级别

    展开全文
  • 百度地图点聚合,更换聚合点图片 根据动态获取的图片经纬度给图片定位,取其中的一个图片做为封面。 思路:先获取所有的聚合点,然后获取每个聚合点里的第一个图片做为封面。 ...

    根据动态获取的图片经纬度给图片定位,取其中的一个图片做为封面。

     

    思路: 先获取所有的聚合点,然后获取每个聚合点里的第一个图片做为封面。

     

    
    
    posted on 2017-12-13 21:29 麦田里的包米 阅读(...) 评论(...) 编辑 收藏

    转载于:https://www.cnblogs.com/guanguan-/p/8034993.html

    展开全文
  • 百度地图点聚合、点点击事件、聚合点击事件、分区域聚合
  • 百度地图点聚合,加载1万个marker-附件资源
  • 百度地图点聚合提高效率

    万次阅读 热门讨论 2017-02-16 14:02:35
    优化百度地图点聚合 参考文献:http://www.cnblogs.com/lightnull/p/6184867.html 百度的点聚合算法 是基于方格和距离的聚合算法,即开始的时候地图上没有任何已知的聚合点,然后遍历所有的点,去计算点的外包...

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

    好的,笔者开始了作死之旅。上面笔者只是生成了50个随机点。

    接下来要测试下1000个点,嗯有点小卡,但是还能操作,

    2000个点,我的天,这shit一样的卡顿是什么鬼!!

    5000个点,好的,完美,动也动不了 简直漂亮

    10000个点,页面无响应。。。。。。。

    ----------我只是一条漂亮的分割线----------

    百度地图 点聚合的部分源码:

    复制代码
    /**
         * 根据所给定的标记,创建聚合点
         * @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);
            }    
        };
    复制代码

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

    先排除所有不在可视范围的点,然后通过比较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 === this._minClusterSize) {
                for (var i = 0; i < len; i++) {
                    this._markers[i].getMap() && this._map.removeOverlay(this._markers[i]);
                }
                
            } 
            this._map.addOverlay(this._clusterMarker);
            this._isReal = true;
            this.updateClusterMarker();
            return true;
        };
    复制代码

    果然不出所料,在addMarker() 方法内不停的去进行dom操作,不卡才怪。为什么度娘就不等计算结束后,在去一次操作完呢,

    于是笔者把标黄的代码抽离了出来给cluster类加了一个render方法, 然后在MarkerClusterer.createClusters方法最后加了一个遍历所有聚合点的操作,代码如下:

    复制代码
    Cluster.prototype.render = function(){
        var len = this._markers.length;
             
        if (len < this._minClusterSize) {
                for (var i = 0; i < len; i++) {
                    this._map.addOverlay(this._markers[i]);
                }
        } else {
                this._map.addOverlay(this._clusterMarker);
                this._isReal = true;
                this.updateClusterMarker();
        }
    }
    复制代码
    var len = this._markers.length;
    for (var i = 0; i < len; i++) {
        if(this._clusters[i]){
            this._clusters[i].render();
        }
    }

    测试比较一下吧!

    Maker数量 原版点聚合js(时间:毫秒 ms) 优化后点聚合js(时间:毫秒 ms)
    100 95 88 60 65
    1000 588 612 146 133
    10000 5840 5772 439 424
    30000 19987 20170 1334 1457

    新手上路!!

     

    贴上修改后的代码:

    复制代码
      1 /**
      2  * @fileoverview MarkerClusterer标记聚合器用来解决加载大量点要素到地图上产生覆盖现象的问题,并提高性能。
      3  * 主入口类是<a href="symbols/BMapLib.MarkerClusterer.html">MarkerClusterer</a>,
      4  * 基于Baidu Map API 1.2。
      5  *
      6  * @author Baidu Map Api Group 
      7  * @version 1.2
      8  */
      9   
     10  
     11 /** 
     12  * @namespace BMap的所有library类均放在BMapLib命名空间下
     13  */
     14 var BMapLib = window.BMapLib = BMapLib || {};
     15 (function(){
     16      
     17     /**
     18      * 获取一个扩展的视图范围,把上下左右都扩大一样的像素值。
     19      * @param {Map} map BMap.Map的实例化对象
     20      * @param {BMap.Bounds} bounds BMap.Bounds的实例化对象
     21      * @param {Number} gridSize 要扩大的像素值
     22      *
     23      * @return {BMap.Bounds} 返回扩大后的视图范围。
     24      */
     25     var getExtendedBounds = function(map, bounds, gridSize){
     26         bounds = cutBoundsInRange(bounds);
     27         var pixelNE = map.pointToPixel(bounds.getNorthEast());
     28         var pixelSW = map.pointToPixel(bounds.getSouthWest()); 
     29         pixelNE.x += gridSize;
     30         pixelNE.y -= gridSize;
     31         pixelSW.x -= gridSize;
     32         pixelSW.y += gridSize;
     33         var newNE = map.pixelToPoint(pixelNE);
     34         var newSW = map.pixelToPoint(pixelSW);
     35         return new BMap.Bounds(newSW, newNE);
     36     };
     37  
     38     /**
     39      * 按照百度地图支持的世界范围对bounds进行边界处理
     40      * @param {BMap.Bounds} bounds BMap.Bounds的实例化对象
     41      *
     42      * @return {BMap.Bounds} 返回不越界的视图范围
     43      */
     44     var cutBoundsInRange = function (bounds) {
     45         var maxX = getRange(bounds.getNorthEast().lng, -180, 180);
     46         var minX = getRange(bounds.getSouthWest().lng, -180, 180);
     47         var maxY = getRange(bounds.getNorthEast().lat, -74, 74);
     48         var minY = getRange(bounds.getSouthWest().lat, -74, 74);
     49         return new BMap.Bounds(new BMap.Point(minX, minY), new BMap.Point(maxX, maxY));
     50     }; 
     51  
     52     /**
     53      * 对单个值进行边界处理。
     54      * @param {Number} i 要处理的数值
     55      * @param {Number} min 下边界值
     56      * @param {Number} max 上边界值
     57      * 
     58      * @return {Number} 返回不越界的数值
     59      */
     60     var getRange = function (i, mix, max) {
     61         mix && (i = Math.max(i, mix));
     62         max && (i = Math.min(i, max));
     63         return i;
     64     };
     65  
     66     /**
     67      * 判断给定的对象是否为数组
     68      * @param {Object} source 要测试的对象
     69      *
     70      * @return {Boolean} 如果是数组返回true,否则返回false
     71      */
     72     var isArray = function (source) {
     73         return '[object Array]' === Object.prototype.toString.call(source);
     74     };
     75  
     76     /**
     77      * 返回item在source中的索引位置
     78      * @param {Object} item 要测试的对象
     79      * @param {Array} source 数组
     80      *
     81      * @return {Number} 如果在数组内,返回索引,否则返回-1
     82      */
     83     var indexOf = function(item, source){
     84         var index = -1;
     85         if(isArray(source)){
     86             if (source.indexOf) {
     87                 index = source.indexOf(item);
     88             } else {
     89                 for (var i = 0, m; m = source[i]; i++) {
     90                     if (m === item) {
     91                         index = i;
     92                         break;
     93                     }
     94                 }
     95             }
     96         }        
     97         return index;
     98     };
     99  
    100     /**
    101      *@exports MarkerClusterer as BMapLib.MarkerClusterer
    102      */
    103     var MarkerClusterer =  
    104         /**
    105          * MarkerClusterer
    106          * @class 用来解决加载大量点要素到地图上产生覆盖现象的问题,并提高性能
    107          * @constructor
    108          * @param {Map} map 地图的一个实例。
    109          * @param {Json Object} options 可选参数,可选项包括:<br />
    110          *    markers {Array<Marker>} 要聚合的标记数组<br />
    111          *    girdSize {Number} 聚合计算时网格的像素大小,默认60<br />
    112          *    maxZoom {Number} 最大的聚合级别,大于该级别就不进行相应的聚合<br />
    113          *    minClusterSize {Number} 最小的聚合数量,小于该数量的不能成为一个聚合,默认为2<br />
    114          *    isAverangeCenter {Boolean} 聚合点的落脚位置是否是所有聚合在内点的平均值,默认为否,落脚在聚合内的第一个点<br />
    115          *    styles {Array<IconStyle>} 自定义聚合后的图标风格,请参考TextIconOverlay类<br />
    116          */
    117         BMapLib.MarkerClusterer = function(map, options){
    118             if (!map){
    119                 return;
    120             }
    121             this._map = map;
    122             this._markers = [];
    123             this._clusters = [];
    124              
    125             var opts = options || {};
    126             this._gridSize = opts["gridSize"] || 60;
    127             this._maxZoom = opts["maxZoom"] || 18;
    128             this._minClusterSize = opts["minClusterSize"] || 2;           
    129             this._isAverageCenter = false;
    130             if (opts['isAverageCenter'] != undefined) {
    131                 this._isAverageCenter = opts['isAverageCenter'];
    132             }    
    133             this._styles = opts["styles"] || [];
    134          
    135             var that = this;
    136             this._map.addEventListener("zoomend",function(){
    137                 that._redraw();     
    138             });
    139      
    140             this._map.addEventListener("moveend",function(){
    141                  that._redraw();     
    142             });
    143  
    144             var mkrs = opts["markers"];
    145             isArray(mkrs) && this.addMarkers(mkrs);
    146         };
    147  
    148     /**
    149      * 添加要聚合的标记数组。
    150      * @param {Array<Marker>} markers 要聚合的标记数组
    151      *
    152      * @return 无返回值。
    153      */
    154     MarkerClusterer.prototype.addMarkers = function(markers){
    155         for(var i = 0, len = markers.length; i <len ; i++){
    156             this._pushMarkerTo(markers[i]);
    157         }
    158         this._createClusters();   
    159     };
    160  
    161     /**
    162      * 把一个标记添加到要聚合的标记数组中
    163      * @param {BMap.Marker} marker 要添加的标记
    164      *
    165      * @return 无返回值。
    166      */
    167     MarkerClusterer.prototype._pushMarkerTo = function(marker){
    168         var index = indexOf(marker, this._markers);
    169         if(index === -1){
    170             marker.isInCluster = false;
    171             this._markers.push(marker);//Marker拖放后enableDragging不做变化,忽略
    172         }
    173     };
    174  
    175     /**
    176      * 添加一个聚合的标记。
    177      * @param {BMap.Marker} marker 要聚合的单个标记。
    178      * @return 无返回值。
    179      */
    180     MarkerClusterer.prototype.addMarker = function(marker) {
    181         this._pushMarkerTo(marker);
    182         this._createClusters();
    183     };
    184  
    185     /**
    186      * 根据所给定的标记,创建聚合点,并且遍历所有聚合点
    187      * @return 无返回值
    188      */
    189     MarkerClusterer.prototype._createClusters = function(){
    190         var mapBounds = this._map.getBounds();
    191         var extendedBounds = getExtendedBounds(this._map, mapBounds, this._gridSize);
    192         for(var i = 0, marker; marker = this._markers[i]; i++){
    193             if(!marker.isInCluster && extendedBounds.containsPoint(marker.getPosition()) ){ 
    194                 this._addToClosestCluster(marker);                
    195             }
    196         }
    197 
    198         var len = this._markers.length;
    199         for (var i = 0; i < len; i++) {
    200             if(this._clusters[i]){
    201                 this._clusters[i].render();
    202             }
    203         }
    204     };
    205  
    206     /**
    207      * 根据标记的位置,把它添加到最近的聚合中
    208      * @param {BMap.Marker} marker 要进行聚合的单个标记
    209      *
    210      * @return 无返回值。
    211      */
    212     MarkerClusterer.prototype._addToClosestCluster = function (marker){
    213         var distance = 4000000;
    214         var clusterToAddTo = null;
    215         var position = marker.getPosition();
    216         for(var i = 0, cluster; cluster = this._clusters[i]; i++){
    217             var center = cluster.getCenter();
    218             if(center){
    219                 var d = this._map.getDistance(center, marker.getPosition());
    220                 if(d < distance){
    221                     distance = d;
    222                     clusterToAddTo = cluster;
    223                 }
    224             }
    225         }
    226      
    227         if (clusterToAddTo && clusterToAddTo.isMarkerInClusterBounds(marker)){
    228             clusterToAddTo.addMarker(marker);
    229         } else {
    230             var cluster = new Cluster(this);
    231             cluster.addMarker(marker);            
    232             this._clusters.push(cluster);
    233         }    
    234     };
    235  
    236     /**
    237      * 清除上一次的聚合的结果
    238      * @return 无返回值。
    239      */
    240     MarkerClusterer.prototype._clearLastClusters = function(){
    241         for(var i = 0, cluster; cluster = this._clusters[i]; i++){            
    242             cluster.remove();
    243         }
    244         this._clusters = [];//置空Cluster数组
    245         this._removeMarkersFromCluster();//把Marker的cluster标记设为false
    246     };
    247  
    248     /**
    249      * 清除某个聚合中的所有标记
    250      * @return 无返回值
    251      */
    252     MarkerClusterer.prototype._removeMarkersFromCluster = function(){
    253         for(var i = 0, marker; marker = this._markers[i]; i++){
    254             marker.isInCluster = false;
    255         }
    256     };
    257     
    258     /**
    259      * 把所有的标记从地图上清除
    260      * @return 无返回值
    261      */
    262     MarkerClusterer.prototype._removeMarkersFromMap = function(){
    263         for(var i = 0, marker; marker = this._markers[i]; i++){
    264             marker.isInCluster = false;
    265             tmplabel = marker.getLabel();
    266             this._map.removeOverlay(marker);       
    267             marker.setLabel(tmplabel);
    268         }
    269     };
    270  
    271     /**
    272      * 删除单个标记
    273      * @param {BMap.Marker} marker 需要被删除的marker
    274      *
    275      * @return {Boolean} 删除成功返回true,否则返回false
    276      */
    277     MarkerClusterer.prototype._removeMarker = function(marker) {
    278         var index = indexOf(marker, this._markers);
    279         if (index === -1) {
    280             return false;
    281         }
    282         tmplabel = marker.getLabel();
    283         this._map.removeOverlay(marker);
    284         marker.setLabel(tmplabel);
    285         this._markers.splice(index, 1);
    286         return true;
    287     };
    288  
    289     /**
    290      * 删除单个标记
    291      * @param {BMap.Marker} marker 需要被删除的marker
    292      *
    293      * @return {Boolean} 删除成功返回true,否则返回false
    294      */
    295     MarkerClusterer.prototype.removeMarker = function(marker) {
    296         var success = this._removeMarker(marker);
    297         if (success) {
    298             this._clearLastClusters();
    299             this._createClusters();
    300         }
    301         return success;
    302     };
    303      
    304     /**
    305      * 删除一组标记
    306      * @param {Array<BMap.Marker>} markers 需要被删除的marker数组
    307      *
    308      * @return {Boolean} 删除成功返回true,否则返回false
    309      */
    310     MarkerClusterer.prototype.removeMarkers = function(markers) {
    311         var success = false;
    312         for (var i = 0; i < markers.length; i++) {
    313             var r = this._removeMarker(markers[i]);
    314             success = success || r; 
    315         }
    316  
    317         if (success) {
    318             this._clearLastClusters();
    319             this._createClusters();
    320         }
    321         return success;
    322     };
    323  
    324     /**
    325      * 从地图上彻底清除所有的标记
    326      * @return 无返回值
    327      */
    328     MarkerClusterer.prototype.clearMarkers = function() {
    329         this._clearLastClusters();
    330         this._removeMarkersFromMap();
    331         this._markers = [];
    332     };
    333  
    334     /**
    335      * 重新生成,比如改变了属性等
    336      * @return 无返回值
    337      */
    338     MarkerClusterer.prototype._redraw = function () {
    339         this._clearLastClusters();
    340         this._createClusters();
    341     };
    342  
    343     /**
    344      * 获取网格大小
    345      * @return {Number} 网格大小
    346      */
    347     MarkerClusterer.prototype.getGridSize = function() {
    348         return this._gridSize;
    349     };
    350  
    351     /**
    352      * 设置网格大小
    353      * @param {Number} size 网格大小
    354      * @return 无返回值
    355      */
    356     MarkerClusterer.prototype.setGridSize = function(size) {
    357         this._gridSize = size;
    358         this._redraw();
    359     };
    360  
    361     /**
    362      * 获取聚合的最大缩放级别。
    363      * @return {Number} 聚合的最大缩放级别。
    364      */
    365     MarkerClusterer.prototype.getMaxZoom = function() {
    366         return this._maxZoom;       
    367     };
    368  
    369     /**
    370      * 设置聚合的最大缩放级别
    371      * @param {Number} maxZoom 聚合的最大缩放级别
    372      * @return 无返回值
    373      */
    374     MarkerClusterer.prototype.setMaxZoom = function(maxZoom) {
    375         this._maxZoom = maxZoom;
    376         this._redraw();
    377     };
    378  
    379     /**
    380      * 获取聚合的样式风格集合
    381      * @return {Array<IconStyle>} 聚合的样式风格集合
    382      */
    383     MarkerClusterer.prototype.getStyles = function() {
    384         return this._styles;
    385     };
    386  
    387     /**
    388      * 设置聚合的样式风格集合
    389      * @param {Array<IconStyle>} styles 样式风格数组
    390      * @return 无返回值
    391      */
    392     MarkerClusterer.prototype.setStyles = function(styles) {
    393         this._styles = styles;
    394         this._redraw();
    395     };
    396  
    397     /**
    398      * 获取单个聚合的最小数量。
    399      * @return {Number} 单个聚合的最小数量。
    400      */
    401     MarkerClusterer.prototype.getMinClusterSize = function() {
    402         return this._minClusterSize;
    403     };
    404  
    405     /**
    406      * 设置单个聚合的最小数量。
    407      * @param {Number} size 单个聚合的最小数量。
    408      * @return 无返回值。
    409      */
    410     MarkerClusterer.prototype.setMinClusterSize = function(size) {
    411         this._minClusterSize = size;
    412         this._redraw();
    413     };
    414  
    415     /**
    416      * 获取单个聚合的落脚点是否是聚合内所有标记的平均中心。
    417      * @return {Boolean} true或false。
    418      */
    419     MarkerClusterer.prototype.isAverageCenter = function() {
    420         return this._isAverageCenter;
    421     };
    422  
    423     /**
    424      * 获取聚合的Map实例。
    425      * @return {Map} Map的示例。
    426      */
    427     MarkerClusterer.prototype.getMap = function() {
    428       return this._map;
    429     };
    430  
    431     /**
    432      * 获取所有的标记数组。
    433      * @return {Array<Marker>} 标记数组。
    434      */
    435     MarkerClusterer.prototype.getMarkers = function() {
    436         return this._markers;
    437     };
    438  
    439     /**
    440      * 获取聚合的总数量。
    441      * @return {Number} 聚合的总数量。
    442      */
    443     MarkerClusterer.prototype.getClustersCount = function() {
    444         var count = 0;
    445         for(var i = 0, cluster; cluster = this._clusters[i]; i++){
    446             cluster.isReal() && count++;     
    447         }
    448         return count;
    449     };
    450  
    451     /**
    452      * @ignore
    453      * Cluster
    454      * @class 表示一个聚合对象,该聚合,包含有N个标记,这N个标记组成的范围,并有予以显示在Map上的TextIconOverlay等。
    455      * @constructor
    456      * @param {MarkerClusterer} markerClusterer 一个标记聚合器示例。
    457      */
    458     function Cluster(markerClusterer){
    459         this._markerClusterer = markerClusterer;
    460         this._map = markerClusterer.getMap();
    461         this._minClusterSize = markerClusterer.getMinClusterSize();
    462         this._isAverageCenter = markerClusterer.isAverageCenter();
    463         this._center = null;//落脚位置
    464         this._markers = [];//这个Cluster中所包含的markers
    465         this._gridBounds = null;//以中心点为准,向四边扩大gridSize个像素的范围,也即网格范围
    466         this._isReal = false; //真的是个聚合
    467      
    468         this._clusterMarker = new BMapLib.TextIconOverlay(this._center, this._markers.length, {"styles":this._markerClusterer.getStyles()});
    469         //this._map.addOverlay(this._clusterMarker);
    470     }
    471     
    472     /**
    473      * 向该聚合添加一个标记。
    474      * @param {Marker} marker 要添加的标记。
    475      * @return 无返回值。
    476      */
    477     Cluster.prototype.addMarker = function(marker){
    478         if(this.isMarkerInCluster(marker)){
    479             return false;
    480         }//也可用marker.isInCluster判断,外面判断OK,这里基本不会命中
    481      
    482         if (!this._center){
    483             this._center = marker.getPosition();
    484             this.updateGridBounds();//
    485         } else {
    486             if(this._isAverageCenter){
    487                 var l = this._markers.length + 1;
    488                 var lat = (this._center.lat * (l - 1) + marker.getPosition().lat) / l;
    489                 var lng = (this._center.lng * (l - 1) + marker.getPosition().lng) / l;
    490                 this._center = new BMap.Point(lng, lat);
    491                 this.updateGridBounds();
    492             }//计算新的Center
    493         }
    494      
    495         marker.isInCluster = true;
    496         this._markers.push(marker);
    497     };
    498     
    499     /**
    500      * 进行dom操作
    501      * @return 无返回值
    502      */
    503     Cluster.prototype.render = function(){
    504         var len = this._markers.length;
    505          
    506         if (len < this._minClusterSize) {
    507             for (var i = 0; i < len; i++) {
    508                 this._map.addOverlay(this._markers[i]);
    509             }
    510         } else {
    511             this._map.addOverlay(this._clusterMarker);
    512             this._isReal = true;
    513             this.updateClusterMarker();
    514         }
    515     }
    516 
    517     /**
    518      * 判断一个标记是否在该聚合中。
    519      * @param {Marker} marker 要判断的标记。
    520      * @return {Boolean} true或false。
    521      */
    522     Cluster.prototype.isMarkerInCluster= function(marker){
    523         if (this._markers.indexOf) {
    524             return this._markers.indexOf(marker) != -1;
    525         } else {
    526             for (var i = 0, m; m = this._markers[i]; i++) {
    527                 if (m === marker) {
    528                     return true;
    529                 }
    530             }
    531         }
    532         return false;
    533     };
    534  
    535     /**
    536      * 判断一个标记是否在该聚合网格范围中。
    537      * @param {Marker} marker 要判断的标记。
    538      * @return {Boolean} true或false。
    539      */
    540     Cluster.prototype.isMarkerInClusterBounds = function(marker) {
    541         return this._gridBounds.containsPoint(marker.getPosition());
    542     };
    543      
    544     Cluster.prototype.isReal = function(marker) {
    545         return this._isReal;
    546     };
    547  
    548     /**
    549      * 更新该聚合的网格范围。
    550      * @return 无返回值。
    551      */
    552     Cluster.prototype.updateGridBounds = function() {
    553         var bounds = new BMap.Bounds(this._center, this._center);
    554         this._gridBounds = getExtendedBounds(this._map, bounds, this._markerClusterer.getGridSize());
    555     };
    556  
    557     /**
    558      * 更新该聚合的显示样式,也即TextIconOverlay。
    559      * @return 无返回值。
    560      */
    561     Cluster.prototype.updateClusterMarker = function () {
    562         if (this._map.getZoom() > this._markerClusterer.getMaxZoom()) {
    563             this._clusterMarker && this._map.removeOverlay(this._clusterMarker);
    564             for (var i = 0, marker; marker = this._markers[i]; i++) {
    565                 this._map.addOverlay(marker);
    566             }
    567             return;
    568         }
    569  
    570         if (this._markers.length < this._minClusterSize) {
    571             this._clusterMarker.hide();
    572             return;
    573         }
    574  
    575         this._clusterMarker.setPosition(this._center);
    576          
    577         this._clusterMarker.setText(this._markers.length);
    578  
    579         var thatMap = this._map;
    580         var thatBounds = this.getBounds();
    581         this._clusterMarker.addEventListener("click", function(event){
    582             thatMap.setViewport(thatBounds);
    583         });
    584  
    585     };
    586  
    587     /**
    588      * 删除该聚合。
    589      * @return 无返回值。
    590      */
    591     Cluster.prototype.remove = function(){
    592         for (var i = 0, m; m = this._markers[i]; i++) {
    593             tmplabel = this._markers[i].getLabel(); 
    594             this._markers[i].getMap() && this._map.removeOverlay(this._markers[i])
    595             this._markers[i].setLabel(tmplabel)
    596         }//清除散的标记点
    597         this._map.removeOverlay(this._clusterMarker);
    598         this._markers.length = 0;
    599         delete this._markers;
    600     }
    601  
    602     /**
    603      * 获取该聚合所包含的所有标记的最小外接矩形的范围。
    604      * @return {BMap.Bounds} 计算出的范围。
    605      */
    606     Cluster.prototype.getBounds = function() {
    607         var bounds = new BMap.Bounds(this._center,this._center);
    608         for (var i = 0, marker; marker = this._markers[i]; i++) {
    609             bounds.extend(marker.getPosition());
    610         }
    611         return bounds;
    612     };
    613  
    614     /**
    615      * 获取该聚合的落脚点。
    616      * @return {BMap.Point} 该聚合的落脚点。
    617      */
    618     Cluster.prototype.getCenter = function() {
    619         return this._center;
    620     };
    621  
    622 })();

    文献来自:http://www.cnblogs.com/anyuan9/p/6232137.html
    展开全文
  • 百度地图点聚合MarkerClusterer,性能优化

    参考文献:http://www.cnblogs.com/lightnull/p/6184867.html

     

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

    好的,笔者开始了作死之旅。上面笔者只是生成了50个随机点。

    接下来要测试下1000个点,嗯有点小卡,但是还能操作,

    2000个点,我的天,这shit一样的卡顿是什么鬼!!

    5000个点,好的,完美,动也动不了 简直漂亮

    10000个点,页面无响应。。。。。。。

    ----------我只是一条漂亮的分割线----------

    百度地图 点聚合的部分源码:

     
    /**
         * 根据所给定的标记,创建聚合点
         * @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);
            }    
        };

     

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

    先排除所有不在可视范围的点,然后通过比较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 === this._minClusterSize) {
                for (var i = 0; i < len; i++) {
                    this._markers[i].getMap() && this._map.removeOverlay(this._markers[i]);
                }
                
            } 
            this._map.addOverlay(this._clusterMarker);
            this._isReal = true;
            this.updateClusterMarker();
            return true;
        };
    复制代码

    果然不出所料,在addMarker() 方法内不停的去进行dom操作,不卡才怪。为什么度娘就不等计算结束后,在去一次操作完呢,

    于是笔者把标黄的代码抽离了出来给cluster类加了一个render方法, 然后在MarkerClusterer.createClusters方法最后加了一个遍历所有聚合点的操作,代码如下:

    复制代码
    Cluster.prototype.render = function(){
        var len = this._markers.length;
             
        if (len < this._minClusterSize) {
                for (var i = 0; i < len; i++) {
                    this._map.addOverlay(this._markers[i]);
                }
        } else {
                this._map.addOverlay(this._clusterMarker);
                this._isReal = true;
                this.updateClusterMarker();
        }
    }
    复制代码
    var len = this._markers.length;
    for (var i = 0; i < len; i++) {
        if(this._clusters[i]){
            this._clusters[i].render();
        }
    }

    测试比较一下吧!

    Maker数量 原版点聚合js(时间:毫秒 ms) 优化后点聚合js(时间:毫秒 ms)
    100 95 88 60 65
    1000 588 612 146 133
    10000 5840 5772 439 424
    30000 19987 20170 1334 1457

    新手上路!!

     

    贴上修改后的代码:

    /**
     * @fileoverview MarkerClusterer标记聚合器用来解决加载大量点要素到地图上产生覆盖现象的问题,并提高性能。
     * 主入口类是<a href="symbols/BMapLib.MarkerClusterer.html">MarkerClusterer</a>,
     * 基于Baidu Map API 1.2。
     *
     * @author Baidu Map Api Group 
     * @version 1.2
     */
      
     
    /** 
     * @namespace BMap的所有library类均放在BMapLib命名空间下
     */
    var BMapLib = window.BMapLib = BMapLib || {};
    (function(){
         
        /**
         * 获取一个扩展的视图范围,把上下左右都扩大一样的像素值。
         * @param {Map} map BMap.Map的实例化对象
         * @param {BMap.Bounds} bounds BMap.Bounds的实例化对象
         * @param {Number} gridSize 要扩大的像素值
         *
         * @return {BMap.Bounds} 返回扩大后的视图范围。
         */
        var getExtendedBounds = function(map, bounds, gridSize){
            bounds = cutBoundsInRange(bounds);
            var pixelNE = map.pointToPixel(bounds.getNorthEast());
            var pixelSW = map.pointToPixel(bounds.getSouthWest()); 
            pixelNE.x += gridSize;
            pixelNE.y -= gridSize;
            pixelSW.x -= gridSize;
            pixelSW.y += gridSize;
            var newNE = map.pixelToPoint(pixelNE);
            var newSW = map.pixelToPoint(pixelSW);
            return new BMap.Bounds(newSW, newNE);
        };
     
        /**
         * 按照百度地图支持的世界范围对bounds进行边界处理
         * @param {BMap.Bounds} bounds BMap.Bounds的实例化对象
         *
         * @return {BMap.Bounds} 返回不越界的视图范围
         */
        var cutBoundsInRange = function (bounds) {
            var maxX = getRange(bounds.getNorthEast().lng, -180, 180);
            var minX = getRange(bounds.getSouthWest().lng, -180, 180);
            var maxY = getRange(bounds.getNorthEast().lat, -74, 74);
            var minY = getRange(bounds.getSouthWest().lat, -74, 74);
            return new BMap.Bounds(new BMap.Point(minX, minY), new BMap.Point(maxX, maxY));
        }; 
     
        /**
         * 对单个值进行边界处理。
         * @param {Number} i 要处理的数值
         * @param {Number} min 下边界值
         * @param {Number} max 上边界值
         * 
         * @return {Number} 返回不越界的数值
         */
        var getRange = function (i, mix, max) {
            mix && (i = Math.max(i, mix));
            max && (i = Math.min(i, max));
            return i;
        };
     
        /**
         * 判断给定的对象是否为数组
         * @param {Object} source 要测试的对象
         *
         * @return {Boolean} 如果是数组返回true,否则返回false
         */
        var isArray = function (source) {
            return '[object Array]' === Object.prototype.toString.call(source);
        };
     
        /**
         * 返回item在source中的索引位置
         * @param {Object} item 要测试的对象
         * @param {Array} source 数组
         *
         * @return {Number} 如果在数组内,返回索引,否则返回-1
         */
        var indexOf = function(item, source){
            var index = -1;
            if(isArray(source)){
                if (source.indexOf) {
                    index = source.indexOf(item);
                } else {
                    for (var i = 0, m; m = source[i]; i++) {
                        if (m === item) {
                            index = i;
                            break;
                        }
                    }
                }
            }        
            return index;
        };
     
        /**
         *@exports MarkerClusterer as BMapLib.MarkerClusterer
         */
        var MarkerClusterer =  
            /**
             * MarkerClusterer
             * @class 用来解决加载大量点要素到地图上产生覆盖现象的问题,并提高性能
             * @constructor
             * @param {Map} map 地图的一个实例。
             * @param {Json Object} options 可选参数,可选项包括:<br />
             *    markers {Array<Marker>} 要聚合的标记数组<br />
             *    girdSize {Number} 聚合计算时网格的像素大小,默认60<br />
             *    maxZoom {Number} 最大的聚合级别,大于该级别就不进行相应的聚合<br />
             *    minClusterSize {Number} 最小的聚合数量,小于该数量的不能成为一个聚合,默认为2<br />
             *    isAverangeCenter {Boolean} 聚合点的落脚位置是否是所有聚合在内点的平均值,默认为否,落脚在聚合内的第一个点<br />
             *    styles {Array<IconStyle>} 自定义聚合后的图标风格,请参考TextIconOverlay类<br />
             */
            BMapLib.MarkerClusterer = function(map, options){
                if (!map){
                    return;
                }
                this._map = map;
                this._markers = [];
                this._clusters = [];
                 
                var opts = options || {};
                this._gridSize = opts["gridSize"] || 60;
                this._maxZoom = opts["maxZoom"] || 18;
                this._minClusterSize = opts["minClusterSize"] || 2;           
                this._isAverageCenter = false;
                if (opts['isAverageCenter'] != undefined) {
                    this._isAverageCenter = opts['isAverageCenter'];
                }    
                this._styles = opts["styles"] || [];
             
                var that = this;
                this._map.addEventListener("zoomend",function(){
                    that._redraw();     
                });
         
                this._map.addEventListener("moveend",function(){
                     that._redraw();     
                });
     
                var mkrs = opts["markers"];
                isArray(mkrs) && this.addMarkers(mkrs);
            };
     
        /**
         * 添加要聚合的标记数组。
         * @param {Array<Marker>} markers 要聚合的标记数组
         *
         * @return 无返回值。
         */
        MarkerClusterer.prototype.addMarkers = function(markers){
            for(var i = 0, len = markers.length; i <len ; i++){
                this._pushMarkerTo(markers[i]);
            }
            this._createClusters();   
        };
     
        /**
         * 把一个标记添加到要聚合的标记数组中
         * @param {BMap.Marker} marker 要添加的标记
         *
         * @return 无返回值。
         */
        MarkerClusterer.prototype._pushMarkerTo = function(marker){
            var index = indexOf(marker, this._markers);
            if(index === -1){
                marker.isInCluster = false;
                this._markers.push(marker);//Marker拖放后enableDragging不做变化,忽略
            }
        };
     
        /**
         * 添加一个聚合的标记。
         * @param {BMap.Marker} marker 要聚合的单个标记。
         * @return 无返回值。
         */
        MarkerClusterer.prototype.addMarker = function(marker) {
            this._pushMarkerTo(marker);
            this._createClusters();
        };
     
        /**
         * 根据所给定的标记,创建聚合点,并且遍历所有聚合点
         * @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);                
                }
            }
    
            var len = this._markers.length;
            for (var i = 0; i < len; i++) {
                if(this._clusters[i]){
                    this._clusters[i].render();
                }
            }
        };
     
        /**
         * 根据标记的位置,把它添加到最近的聚合中
         * @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);
            }    
        };
     
        /**
         * 清除上一次的聚合的结果
         * @return 无返回值。
         */
        MarkerClusterer.prototype._clearLastClusters = function(){
            for(var i = 0, cluster; cluster = this._clusters[i]; i++){            
                cluster.remove();
            }
            this._clusters = [];//置空Cluster数组
            this._removeMarkersFromCluster();//把Marker的cluster标记设为false
        };
     
        /**
         * 清除某个聚合中的所有标记
         * @return 无返回值
         */
        MarkerClusterer.prototype._removeMarkersFromCluster = function(){
            for(var i = 0, marker; marker = this._markers[i]; i++){
                marker.isInCluster = false;
            }
        };
        
        /**
         * 把所有的标记从地图上清除
         * @return 无返回值
         */
        MarkerClusterer.prototype._removeMarkersFromMap = function(){
            for(var i = 0, marker; marker = this._markers[i]; i++){
                marker.isInCluster = false;
                tmplabel = marker.getLabel();
                this._map.removeOverlay(marker);       
                marker.setLabel(tmplabel);
            }
        };
     
        /**
         * 删除单个标记
         * @param {BMap.Marker} marker 需要被删除的marker
         *
         * @return {Boolean} 删除成功返回true,否则返回false
         */
        MarkerClusterer.prototype._removeMarker = function(marker) {
            var index = indexOf(marker, this._markers);
            if (index === -1) {
                return false;
            }
            tmplabel = marker.getLabel();
            this._map.removeOverlay(marker);
            marker.setLabel(tmplabel);
            this._markers.splice(index, 1);
            return true;
        };
     
        /**
         * 删除单个标记
         * @param {BMap.Marker} marker 需要被删除的marker
         *
         * @return {Boolean} 删除成功返回true,否则返回false
         */
        MarkerClusterer.prototype.removeMarker = function(marker) {
            var success = this._removeMarker(marker);
            if (success) {
                this._clearLastClusters();
                this._createClusters();
            }
            return success;
        };
         
        /**
         * 删除一组标记
         * @param {Array<BMap.Marker>} markers 需要被删除的marker数组
         *
         * @return {Boolean} 删除成功返回true,否则返回false
         */
        MarkerClusterer.prototype.removeMarkers = function(markers) {
            var success = false;
            for (var i = 0; i < markers.length; i++) {
                var r = this._removeMarker(markers[i]);
                success = success || r; 
            }
     
            if (success) {
                this._clearLastClusters();
                this._createClusters();
            }
            return success;
        };
     
        /**
         * 从地图上彻底清除所有的标记
         * @return 无返回值
         */
        MarkerClusterer.prototype.clearMarkers = function() {
            this._clearLastClusters();
            this._removeMarkersFromMap();
            this._markers = [];
        };
     
        /**
         * 重新生成,比如改变了属性等
         * @return 无返回值
         */
        MarkerClusterer.prototype._redraw = function () {
            this._clearLastClusters();
            this._createClusters();
        };
     
        /**
         * 获取网格大小
         * @return {Number} 网格大小
         */
        MarkerClusterer.prototype.getGridSize = function() {
            return this._gridSize;
        };
     
        /**
         * 设置网格大小
         * @param {Number} size 网格大小
         * @return 无返回值
         */
        MarkerClusterer.prototype.setGridSize = function(size) {
            this._gridSize = size;
            this._redraw();
        };
     
        /**
         * 获取聚合的最大缩放级别。
         * @return {Number} 聚合的最大缩放级别。
         */
        MarkerClusterer.prototype.getMaxZoom = function() {
            return this._maxZoom;       
        };
     
        /**
         * 设置聚合的最大缩放级别
         * @param {Number} maxZoom 聚合的最大缩放级别
         * @return 无返回值
         */
        MarkerClusterer.prototype.setMaxZoom = function(maxZoom) {
            this._maxZoom = maxZoom;
            this._redraw();
        };
     
        /**
         * 获取聚合的样式风格集合
         * @return {Array<IconStyle>} 聚合的样式风格集合
         */
        MarkerClusterer.prototype.getStyles = function() {
            return this._styles;
        };
     
        /**
         * 设置聚合的样式风格集合
         * @param {Array<IconStyle>} styles 样式风格数组
         * @return 无返回值
         */
        MarkerClusterer.prototype.setStyles = function(styles) {
            this._styles = styles;
            this._redraw();
        };
     
        /**
         * 获取单个聚合的最小数量。
         * @return {Number} 单个聚合的最小数量。
         */
        MarkerClusterer.prototype.getMinClusterSize = function() {
            return this._minClusterSize;
        };
     
        /**
         * 设置单个聚合的最小数量。
         * @param {Number} size 单个聚合的最小数量。
         * @return 无返回值。
         */
        MarkerClusterer.prototype.setMinClusterSize = function(size) {
            this._minClusterSize = size;
            this._redraw();
        };
     
        /**
         * 获取单个聚合的落脚点是否是聚合内所有标记的平均中心。
         * @return {Boolean} true或false。
         */
        MarkerClusterer.prototype.isAverageCenter = function() {
            return this._isAverageCenter;
        };
     
        /**
         * 获取聚合的Map实例。
         * @return {Map} Map的示例。
         */
        MarkerClusterer.prototype.getMap = function() {
          return this._map;
        };
     
        /**
         * 获取所有的标记数组。
         * @return {Array<Marker>} 标记数组。
         */
        MarkerClusterer.prototype.getMarkers = function() {
            return this._markers;
        };
     
        /**
         * 获取聚合的总数量。
         * @return {Number} 聚合的总数量。
         */
        MarkerClusterer.prototype.getClustersCount = function() {
            var count = 0;
            for(var i = 0, cluster; cluster = this._clusters[i]; i++){
                cluster.isReal() && count++;     
            }
            return count;
        };
     
        /**
         * @ignore
         * Cluster
         * @class 表示一个聚合对象,该聚合,包含有N个标记,这N个标记组成的范围,并有予以显示在Map上的TextIconOverlay等。
         * @constructor
         * @param {MarkerClusterer} markerClusterer 一个标记聚合器示例。
         */
        function Cluster(markerClusterer){
            this._markerClusterer = markerClusterer;
            this._map = markerClusterer.getMap();
            this._minClusterSize = markerClusterer.getMinClusterSize();
            this._isAverageCenter = markerClusterer.isAverageCenter();
            this._center = null;//落脚位置
            this._markers = [];//这个Cluster中所包含的markers
            this._gridBounds = null;//以中心点为准,向四边扩大gridSize个像素的范围,也即网格范围
            this._isReal = false; //真的是个聚合
         
            this._clusterMarker = new BMapLib.TextIconOverlay(this._center, this._markers.length, {"styles":this._markerClusterer.getStyles()});
            //this._map.addOverlay(this._clusterMarker);
        }
        
        /**
         * 向该聚合添加一个标记。
         * @param {Marker} marker 要添加的标记。
         * @return 无返回值。
         */
        Cluster.prototype.addMarker = function(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);
        };
        
        /**
         * 进行dom操作
         * @return 无返回值
         */
        Cluster.prototype.render = function(){
            var len = this._markers.length;
             
            if (len < this._minClusterSize) {
                for (var i = 0; i < len; i++) {
                    this._map.addOverlay(this._markers[i]);
                }
            } else {
                this._map.addOverlay(this._clusterMarker);
                this._isReal = true;
                this.updateClusterMarker();
            }
        }
    
        /**
         * 判断一个标记是否在该聚合中。
         * @param {Marker} marker 要判断的标记。
         * @return {Boolean} true或false。
         */
        Cluster.prototype.isMarkerInCluster= function(marker){
            if (this._markers.indexOf) {
                return this._markers.indexOf(marker) != -1;
            } else {
                for (var i = 0, m; m = this._markers[i]; i++) {
                    if (m === marker) {
                        return true;
                    }
                }
            }
            return false;
        };
     
        /**
         * 判断一个标记是否在该聚合网格范围中。
         * @param {Marker} marker 要判断的标记。
         * @return {Boolean} true或false。
         */
        Cluster.prototype.isMarkerInClusterBounds = function(marker) {
            return this._gridBounds.containsPoint(marker.getPosition());
        };
         
        Cluster.prototype.isReal = function(marker) {
            return this._isReal;
        };
     
        /**
         * 更新该聚合的网格范围。
         * @return 无返回值。
         */
        Cluster.prototype.updateGridBounds = function() {
            var bounds = new BMap.Bounds(this._center, this._center);
            this._gridBounds = getExtendedBounds(this._map, bounds, this._markerClusterer.getGridSize());
        };
     
        /**
         * 更新该聚合的显示样式,也即TextIconOverlay。
         * @return 无返回值。
         */
        Cluster.prototype.updateClusterMarker = function () {
            if (this._map.getZoom() > this._markerClusterer.getMaxZoom()) {
                this._clusterMarker && this._map.removeOverlay(this._clusterMarker);
                for (var i = 0, marker; marker = this._markers[i]; i++) {
                    this._map.addOverlay(marker);
                }
                return;
            }
     
            if (this._markers.length < this._minClusterSize) {
                this._clusterMarker.hide();
                return;
            }
     
            this._clusterMarker.setPosition(this._center);
             
            this._clusterMarker.setText(this._markers.length);
     
            var thatMap = this._map;
            var thatBounds = this.getBounds();
            this._clusterMarker.addEventListener("click", function(event){
                thatMap.setViewport(thatBounds);
            });
     
        };
     
        /**
         * 删除该聚合。
         * @return 无返回值。
         */
        Cluster.prototype.remove = function(){
            for (var i = 0, m; m = this._markers[i]; i++) {
                tmplabel = this._markers[i].getLabel(); 
                this._markers[i].getMap() && this._map.removeOverlay(this._markers[i])
                this._markers[i].setLabel(tmplabel)
            }//清除散的标记点
            this._map.removeOverlay(this._clusterMarker);
            this._markers.length = 0;
            delete this._markers;
        }
     
        /**
         * 获取该聚合所包含的所有标记的最小外接矩形的范围。
         * @return {BMap.Bounds} 计算出的范围。
         */
        Cluster.prototype.getBounds = function() {
            var bounds = new BMap.Bounds(this._center,this._center);
            for (var i = 0, marker; marker = this._markers[i]; i++) {
                bounds.extend(marker.getPosition());
            }
            return bounds;
        };
     
        /**
         * 获取该聚合的落脚点。
         * @return {BMap.Point} 该聚合的落脚点。
         */
        Cluster.prototype.getCenter = function() {
            return this._center;
        };
     
    })();


     

      

    展开全文
  • 公司要求做个百度地图点聚合的性能优化,需一次性加载9万条数据。 记录下自己的优化过程。(只想看优化代码的可直接移步:步骤三) 一、引入百度地图 vue项目中,在index.html文件中用script标签引入百度地图...
  • 百度地图点聚合实现方法

    千次阅读 2017-01-27 11:04:58
    百度地图点聚合代码如下 //基本配置 var map = new BMap.Map("mapDiv"); map.enableScrollWheelZoom(); var point = new BMap.Point(118.404, 39.915);
  • Android百度地图点聚合开发自v3.3.0版本起,SDK提供了给Marker增加动画的能力,具体实现方法如下:// 通过marker的icons设置一组图片,再通过period设置多少帧刷新一次图片资源这是官方的介绍,下面看看具体实现方法...
  • android开发百度地图点聚合功能

    千次阅读 2018-09-21 15:02:03
    android开发百度地图点聚合功能 第一次写博客。。。本来是不想写的,一时心血来潮(冲动)又无聊,想搞点事情,所以就尝试写写博客。也不知道怎么写呢。我就按照我实现功能的步骤来写吧! 首先,我们得去准备...
  • 在使用百度地图点聚合时,使用map.clearOverlays(); var allOverlay = map.getOverlays(); map.removeOverlay(allOverlay);都无法清除之前的点聚合,我想问怎么样才能清除之前的所有点聚合
  • 百度地图点聚合缩放,label标签消失

    千次阅读 2017-11-30 19:58:37
    百度地图点聚合缩放,label标签消失
  • 百度地图点聚合开发-地图找房功能

    万次阅读 多人点赞 2017-02-17 15:55:26
    因项目需要用到点聚合的功能,因此研究了一下百度地图的聚合API。 这是一个基于百度地图API和百度地图开源库聚合marker开发的一个地图找房的demo。 主要功能如下: 仿照http://www.wkzf.com/nmap.html这...
  • 解决方法建立在已经修改过点聚合渲染逻辑的基础上(百度地图点聚合优化),CSDN上面的好多文章都是参考的这个。 修改过后的代码 就是添加了一个渲染方法来渲染DOM。 如果你想点击事件弹出自己想要设置的东西...
  • 百度地图多点聚合(标注与信息窗口)最佳视野
  • android百度地图点聚合自定义marker,本来以为很简单的的一个点聚合自定义marker,搞了三天 百度了三天,大家一定要注意一定要注意一定要注意 1.外层布局用LinearLayout (其实这一点我没有试,只是百度上说这样就搞...
  • 优化百度地图点聚合

    2016-12-15 21:15:00
    百度点聚合算法 是基于方格和距离的聚合算法,即开始的时候地图上没有任何已知的聚合点,然后遍历所有的点,去计算点的外包正方形(由gridSize指定),若此点的外包正方形与现有的聚合点的外包正方形不相交,则...
  • 百度地图点聚合改造

    2017-11-06 12:23:32
    前几天,一个老铁问了我关于百度地图聚合的问题,这个聚合算法主要是百度谢好的,我们不做深究,但是关于表层的一些修改,比如聚合物图标,以及选中效果(点击聚合图标自动放大)等需要我们自己手动 添加代码了,...
  • 解决百度地图点聚合缩放Lable消失 亲测有效 javascript API

空空如也

空空如也

1 2 3 4 5 ... 19
收藏数 375
精华内容 150
关键字:

百度地图点聚合