百度地图中自定义点聚合实现

百度地图中自定义点聚合实现

点聚合 (MarkerClusterer 标记聚合器)用来解决加载大量点要素到地图上产生覆盖现象的问题,并提高性能。

点聚合的实现原理是按照以某点为中心的正方形作为区域,把此区域的点聚合在一个点上,并随着地图比例尺改变此点区域大小,同时改变聚合点的数量。

默认百度地图的聚合marker效果如下:

官方聚合示例:http://lbsyun.baidu.com/jsdemo.htm#c1_4

  • 点击聚合点默认放大
    百度地图中自定义点聚合实现

在实际项目开发中,我遇到了点聚合的一个难题:如何实现自定义聚合点点击事件。

如果直接在源码上修改,时间成本很高,

聚合点默认是没有点击监听事件的,而marker有点击监听事件

因此最终得到一个解决方案:
思路:

1. 根据百度聚合API创建聚合点,但是只需要用到点聚合后的数据,利用自定义样式进行隐藏此聚合点(目的是消除默认聚合点会点击放大效果)
2. 拿到数据后创建一个自定义标注marker,可设置标注样式(相当于利用标注模拟一个聚合点)
3. 创建标注的label,自定义label样式,用来显示聚合数量(利用聚合API的数据可得到聚合点的marker数量,进行自定义label样式模拟聚合点数字的显示)
4. 给marker设置点击监听事件,自定义事件函数内容

示例效果:
百度地图中自定义点聚合实现下面是具体实现:

核心代码部分:

   var datas = [{
        'localtion': '120.585239,31.298881'
    }, {
        'localtion': '120.585239,31.298881'    
    }, {
        'localtion': '120.585239,31.298881'    
    }, {
        'localtion': '120.585239,31.298881'    
    }, {
        'localtion': '120.585239,31.298881'   
    }]
    //先创建初始marker点
    var markers = [];
    for (var i = 0; i < datas.length; i++) {
        var data = datas[i];
        var localtion = data.localtion.split(',');
        var m = new BMap.Marker(new BMap.Point(localtion[0], localtion[1]));
        m.data = data;
        markers.push(m);
    }
    //调用聚合封装函数
    markerClustersPoint(markers);
    //
    //地图缩放重新计算聚合点
    map.addEventListener("zoomend",function(){
        markerClustersPoint(markers);
    });
    //
    //聚合添加
    markerClustersPoint(markers) {
      if (markerClusterer) {
        markerClusterer.clearMarkers();//清除聚合
      }
      //添加点聚合API(index.html中需引入文件)
      //  <script type="text/javascript" src="http://api.map.baidu.com/library/TextIconOverlay/1.2/src/TextIconOverlay_min.js">
      //  </script>
      //  <script type="text/javascript" src="http://api.map.baidu.com/library/MarkerClusterer/1.2/src/MarkerClusterer_min.js">
      //  </script>
      markerClusterer = new BMapLib.MarkerClusterer(this.map, {
        markers: markers,
        minClusterSize: 3, //最小的聚合数量,小于该数量的不能成为一个聚合,默认为2
        styles: [
          {
            //此处仅放置style,不要写任何内容,否则会有默认聚合的数字显示溢出
            // url: "img/info.png",
            // size: new BMap.Size(0, 0)
          }
        ]
      });
      console.log("进入聚合函数markerClusterer", markerClusterer);
      //
      // 拿到所有的聚合点
      //markerClusterer中的 _clusters是一个数组,包含了可视范围的所有聚合点   
      var cluster = markerClusterer._clusters;
      var oldmk = [];
      for (var i = 0; i < cluster.length; i++) {
       //cluster[i]._markers中包含此聚合点的所有marker集合
       //marker长度大于2时不进行聚合效果显示
        if (cluster[i]._markers.length < 2) continue;
        //自定义函数内容,可进行聚合点数据获取操作
        //......
        //......
        //拿到聚合点中的marker数量,用于数字显示
        var cluserMakerSum = cluster[i]._markers.length;
        //添加marker
        oldmk.push(addMarkerCluser(cluster[i]._center));
      }
    },
   // 标记自定义marker
    addMarkerCluser(point) {
      var markerdef = new BMap.Marker(point, {
        // icon: 设置marker样式
        icon: new BMap.Symbol(BMap_Symbol_SHAPE_CIRCLE, {
          scale: 20,
          strokeWeight: 1,
          strokeColor: "white",
          fillColor: "blue",
          fillOpacity: 0.59
        })
      });
      //设置marker的label
      var labelTitleCluser = cluserMakerSum ;
      let label = new BMap.Label(labelTitleCluser, {
        offset: new BMap.Size(12, 12)
      });
      //设置label样式
      label.setStyle({
        color: "#fff",
        fontSize: "14px",
        backgroundColor: "0.05",
        border: "0px "
      });
      markerdef.setLabel(label);
      //监听点击事件
      markerdef.addEventListener("click", function() {
        console.log("点击自定义聚合maker");        
      });
      map.addOverlay(markerdef);
      //
      return markerdef;
    },