MarkerClustererPlus 如何为聚类图像设置不同的大小?

MarkerClusterPlus How to have different sizes for cluster images?

我正在尝试制作一个集群地图,根据集群大小调整图标的大小。 我使用的是 masterclusterplus 库,我已经做了一些调整,以便能够在同一张地图上拥有多个组。 我关注了这个问题:MarkerClustererPlus: set icon color/url independent of size 组里的每个圆都有相同的半径,我不知道怎么改。

代码:

function loadMapData() {

    var me = this;

    var map = document.getElementById("map");

    var lat = 50;
    var long = 12;
    var type = google.maps.MapTypeId["ROADMAP"];
    var zoom = 4;

    var center = new google.maps.LatLng(lat, long);

    var options = {
        'zoom': zoom,
        'center': center,
        'mapTypeId': type
    };

    var map = new google.maps.Map(map, options);
    var markers = [];

    var maxLat = 70;
    var minLat = 37;
    var maxLong = 50;
    var minLong = -8;


    for (var j = 0; j < 300; j++) {

        var marker = new google.maps.Marker({
            position: new google.maps.LatLng(me.getRandom(minLat, maxLat),
                                             me.getRandom(minLong, maxLong)),
        });
        markers.push(marker);
    }


    var mcOptions = {
        enableRetinaIcons: true,
        styles: [{
            textColor: 'black',
            url: '/mapapp/themes/4.svg',
            "height": 80,
            "width": 80
        }]
    };

    var mc = new MarkerClusterer(map, markers, mcOptions);


    var sizes = [];
    for (var j = 0; j < 300; j++) {

        var marker = new google.maps.Marker({
            position: new google.maps.LatLng(me.getRandom(minLat, maxLat),
                                             me.getRandom(minLong, maxLong)),
        });

        markers.push(marker);

        var r = j + 30;
        sizes.push(r);
    }

    var mcOptions = {
        enableRetinaIcons: true,
        imageSizes: [20,30,40,50,60,70],
         styles: [{
            textColor: 'black',
            url: '/mapapp/themes/3.svg',
             width: 40,
             height: 40
        }]
    };
    var mc = new MarkerClusterer(map, markers, mcOptions);

}



function getRandom(min, max) {
    return Math.random() * (max - min + 1) + min;
}

如果不修改库,这是不可能的,因为库需要一组预定义的样式。

通过 CSS 而不是图像创建圆圈的可能方法:

覆盖 createCss 方法以对集群应用动态大小:

ClusterIcon.prototype.createCss = function(pos) {
  var size = Math.min(this.cluster_.getMarkers().length + 10,
      100 //possible max-size of a cluster-icon
    ),

    style = ['border-radius : 50%',
      'line-height   : ' + size + 'px',
      'cursor        : pointer',
      'position      : absolute',
      'top           : ' + pos.y + 'px',
      'left          : ' + pos.x + 'px',
      'width         : ' + size + 'px',
      'height        : ' + size + 'px'
    ];
  return style.join(";") + ';';
};

function randPos() {
  return new google.maps.LatLng(((Math.random() * 16000 - 8000) / 100), ((Math.random() * 34000 - 17000) / 100));
}

function initialize() {
  var center = new google.maps.LatLng(37.4419, -122.1419);

  var map = new google.maps.Map(document.getElementById('map'), {
    zoom: 1,
    center: center,
    mapTypeId: google.maps.MapTypeId.ROADMAP
  });

  var groups = {
    a: {
      markers: [],
      mc: null,
      color: 'red'
    },
    b: {
      markers: [],
      mc: null,
      color: 'gold'
    },
    c: {
      markers: [],
      mc: null,
      color: 'purple'
    }
  };
  for (var k in groups) {
    for (var i = 0; i < 300; ++i) {
      groups[k].markers.push(new google.maps.Marker({
        map: map,
        position: randPos()
      }));
    }
    groups[k].mc = new MarkerClusterer(map,
      groups[k].markers, {
        enableRetinaIcons: true,
        clusterClass: 'cluster cluster_' + groups[k].color
      });
  }


}
google.maps.event.addDomListener(window, 'load', initialize);
html,
body,
#map {
  height: 100%;
  padding: 0;
  margin: 0;
}
.cluster {
  display: table;
  box-shadow: 0px 0px 1px 1px rgba(0, 0, 0, 0.5);
}
.cluster img {
  display: none
}
.cluster div {
  color: inherit !important;
  display: table-cell;
  vertical-align: middle;
  width: 100% !important;
  height: 100% !important;
  line-height: inherit !important;
}
/*custom cluster-styles*/

.cluster_red {
  background: red;
}
.cluster_gold {
  background: gold;
}
.cluster_purple {
  background: purple;
  color: #fff !important
}
<script src="http://maps.googleapis.com/maps/api/js?v=3"></script>
<script type="text/javascript" src="http://google-maps-utility-library-v3.googlecode.com/svn/trunk/markerclustererplus/src/markerclusterer.js"></script>
<div id="map"></div>

使用背景图像的示例(星标通过 svg ,只有 CSS 已更改)

ClusterIcon.prototype.createCss = function(pos) {
  var size = Math.min(this.cluster_.getMarkers().length + 20,
      100 //possible max-size of a cluster-icon
    ),

    style = ['border-radius : 50%',
      'line-height   : ' + size + 'px',
      'cursor        : pointer',
      'position      : absolute',
      'top           : ' + pos.y + 'px',
      'left          : ' + pos.x + 'px',
      'width         : ' + size + 'px',
      'height        : ' + size + 'px'
    ];
  return style.join(";") + ';';
};

function randPos() {
  return new google.maps.LatLng(((Math.random() * 16000 - 8000) / 100), ((Math.random() * 34000 - 17000) / 100));
}

function initialize() {
  var center = new google.maps.LatLng(37.4419, -122.1419);

  var map = new google.maps.Map(document.getElementById('map'), {
    zoom: 1,
    center: center,
    mapTypeId: google.maps.MapTypeId.ROADMAP
  });

  var groups = {
    a: {
      markers: [],
      mc: null,
      color: 'red'
    },
    b: {
      markers: [],
      mc: null,
      color: 'gold'
    },
    c: {
      markers: [],
      mc: null,
      color: 'purple'
    }
  };
  for (var k in groups) {
    for (var i = 0; i < 300; ++i) {
      groups[k].markers.push(new google.maps.Marker({
        map: map,
        position: randPos()
      }));
    }
    groups[k].mc = new MarkerClusterer(map,
      groups[k].markers, {
        enableRetinaIcons: true,
        clusterClass: 'cluster cluster_' + groups[k].color
      });
  }


}
google.maps.event.addDomListener(window, 'load', initialize);
      html,
      body,
      #map {
        height: 100%;
        padding: 0;
        margin: 0;
      }
      .cluster {
        display: table;
        background-size: cover;
      }
      .cluster img {
        display: none
      }
      .cluster div {
        color: inherit !important;
        display: table-cell;
        vertical-align: middle;
        width: 100% !important;
        height: 100% !important;
        line-height: inherit !important;
      }
      /*custom cluster-styles*/
      .cluster_red {
        background-image: url(data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0idXRmLTgiPz4KPCFET0NUWVBFIHN2ZyBQVUJMSUMgIi0vL1czQy8vRFREIFNWRyAxLjEvL0VOIiAiaHR0cDovL3d3dy53My5vcmcvR3JhcGhpY3MvU1ZHLzEuMS9EVEQvc3ZnMTEuZHRkIj4KPHN2ZyB2ZXJzaW9uPSIxLjEiIGlkPSJMYXllcl8xIiB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHhtbG5zOnhsaW5rPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5L3hsaW5rIiB4PSIwcHgiIHk9IjBweCIKCSB3aWR0aD0iNTEycHgiIGhlaWdodD0iNTEycHgiIHZpZXdCb3g9IjAgMCA1MTIgNTEyIiBlbmFibGUtYmFja2dyb3VuZD0ibmV3IDAgMCA1MTIgNTEyIiB4bWw6c3BhY2U9InByZXNlcnZlIj4KPHBvbHlnb24gZmlsbD0icmVkIiBzdHJva2U9ImJsYWNrIiBzdHJva2Utd2lkdGg9IjEiIHN0cm9rZS1saW5lY2FwPSJyb3VuZCIgc3Ryb2tlLWxpbmVqb2luPSJyb3VuZCIgc3Ryb2tlLW1pdGVybGltaXQ9IjEwIiBwb2ludHM9IgoJMjU5LjIxNiwyOS45NDIgMzMwLjI3LDE3My45MTkgNDg5LjE2LDE5Ny4wMDcgMzc0LjE4NSwzMDkuMDggNDAxLjMzLDQ2Ny4zMSAyNTkuMjE2LDM5Mi42MTIgMTE3LjEwNCw0NjcuMzEgMTQ0LjI1LDMwOS4wOCAKCTI5LjI3NCwxOTcuMDA3IDE4OC4xNjUsMTczLjkxOSAiLz4KPC9zdmc+);
      }
      .cluster_gold {
        background-image: url(data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0idXRmLTgiPz4KPCFET0NUWVBFIHN2ZyBQVUJMSUMgIi0vL1czQy8vRFREIFNWRyAxLjEvL0VOIiAiaHR0cDovL3d3dy53My5vcmcvR3JhcGhpY3MvU1ZHLzEuMS9EVEQvc3ZnMTEuZHRkIj4KPHN2ZyB2ZXJzaW9uPSIxLjEiIGlkPSJMYXllcl8xIiB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHhtbG5zOnhsaW5rPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5L3hsaW5rIiB4PSIwcHgiIHk9IjBweCIKCSB3aWR0aD0iNTEycHgiIGhlaWdodD0iNTEycHgiIHZpZXdCb3g9IjAgMCA1MTIgNTEyIiBlbmFibGUtYmFja2dyb3VuZD0ibmV3IDAgMCA1MTIgNTEyIiB4bWw6c3BhY2U9InByZXNlcnZlIj4KPHBvbHlnb24gZmlsbD0iZ29sZCIgc3Ryb2tlPSJibGFjayIgc3Ryb2tlLXdpZHRoPSIxIiBzdHJva2UtbGluZWNhcD0icm91bmQiIHN0cm9rZS1saW5lam9pbj0icm91bmQiIHN0cm9rZS1taXRlcmxpbWl0PSIxMCIgcG9pbnRzPSIKCTI1OS4yMTYsMjkuOTQyIDMzMC4yNywxNzMuOTE5IDQ4OS4xNiwxOTcuMDA3IDM3NC4xODUsMzA5LjA4IDQwMS4zMyw0NjcuMzEgMjU5LjIxNiwzOTIuNjEyIDExNy4xMDQsNDY3LjMxIDE0NC4yNSwzMDkuMDggCgkyOS4yNzQsMTk3LjAwNyAxODguMTY1LDE3My45MTkgIi8+Cjwvc3ZnPg==);
      }
      .cluster_purple {
        background-image: url(data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0idXRmLTgiPz4KPCFET0NUWVBFIHN2ZyBQVUJMSUMgIi0vL1czQy8vRFREIFNWRyAxLjEvL0VOIiAiaHR0cDovL3d3dy53My5vcmcvR3JhcGhpY3MvU1ZHLzEuMS9EVEQvc3ZnMTEuZHRkIj4KPHN2ZyB2ZXJzaW9uPSIxLjEiIGlkPSJMYXllcl8xIiB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHhtbG5zOnhsaW5rPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5L3hsaW5rIiB4PSIwcHgiIHk9IjBweCIKCSB3aWR0aD0iNTEycHgiIGhlaWdodD0iNTEycHgiIHZpZXdCb3g9IjAgMCA1MTIgNTEyIiBlbmFibGUtYmFja2dyb3VuZD0ibmV3IDAgMCA1MTIgNTEyIiB4bWw6c3BhY2U9InByZXNlcnZlIj4KPHBvbHlnb24gZmlsbD0icHVycGxlIiBzdHJva2U9ImJsYWNrIiBzdHJva2Utd2lkdGg9IjEiIHN0cm9rZS1saW5lY2FwPSJyb3VuZCIgc3Ryb2tlLWxpbmVqb2luPSJyb3VuZCIgc3Ryb2tlLW1pdGVybGltaXQ9IjEwIiBwb2ludHM9IgoJMjU5LjIxNiwyOS45NDIgMzMwLjI3LDE3My45MTkgNDg5LjE2LDE5Ny4wMDcgMzc0LjE4NSwzMDkuMDggNDAxLjMzLDQ2Ny4zMSAyNTkuMjE2LDM5Mi42MTIgMTE3LjEwNCw0NjcuMzEgMTQ0LjI1LDMwOS4wOCAKCTI5LjI3NCwxOTcuMDA3IDE4OC4xNjUsMTczLjkxOSAiLz4KPC9zdmc+);
        color: #fff !important
      }
<script src="http://maps.googleapis.com/maps/api/js?v=3"></script>
<script type="text/javascript" src="http://google-maps-utility-library-v3.googlecode.com/svn/trunk/markerclustererplus/src/markerclusterer.js"></script>
<div id="map"></div>

感谢上一个问题,我通过这样做设法解决了我的问题:

创建一个通用方法来计算大小:

    ClusterIcon.prototype.getImgSize = function getImgSize(){

  return Math.min(this.cluster_.getMarkers().length + 20,
      100 //possible max-size of a cluster-icon
    );
}

覆盖 createCss

ClusterIcon.prototype.createCss = function (pos) {

    var size = this.getImgSize();
    var style = [
      'line-height   : ' +  size + 'px',
      'cursor        : pointer',
      'position      : absolute',
      'top           : ' + (pos.y + this.height_/2 - size /2) + 'px',
      'left          : ' + (pos.x + this.width_/2 - size /2) + 'px',
      'width         : ' +  size + 'px',
      'height        : ' +  size + 'px'
    ];
  return style.join(";") + ';';
};

覆盖计算图像属性的方法:

ClusterIcon.prototype.show = function () {
  if (this.div_) {
    var img = "";
    // NOTE: values must be specified in px units
    var bp = this.backgroundPosition_.split(" ");
    var spriteH = parseInt(bp[0].trim(), 10);
    var spriteV = parseInt(bp[1].trim(), 10);
    var pos = this.getPosFromLatLng_(this.center_);
    this.div_.style.cssText = this.createCss(pos);
    img = "<img src='" + this.url_ + "' style='position: absolute; top: " + spriteV + "px; left: " + spriteH + "px;";
    if (!this.cluster_.getMarkerClusterer().enableRetinaIcons_) {
      img += "clip: rect(" + (-1 * spriteV) + "px, " + ((-1 * spriteH) + this.width_) + "px, " +
          ((-1 * spriteV) + this.height_) + "px, " + (-1 * spriteH) + "px);";
    }
    else {
        img += "width: " + this.getImgSize() + "px;" + "height: " + this.getImgSize() + "px;";
    }
    img += "'>";
    this.div_.innerHTML = img + "<div style='" +
        "position: absolute;" +
        "top: " + this.anchorText_[0] + "px;" +
        "left: " + this.anchorText_[1] + "px;" +
        "color: " + this.textColor_ + ";" +
        "font-size: " + this.textSize_ + "px;" +
        "font-family: " + this.fontFamily_ + ";" +
        "font-weight: " + this.fontWeight_ + ";" +
        "font-style: " + this.fontStyle_ + ";" +
        "text-decoration: " + this.textDecoration_ + ";" +
        "text-align: center;" +
        "width: " + this.getImgSize() + "px;" +
        "line-height:" + this.getImgSize() + "px;" +
        "'>" + (this.cluster_.hideLabel_ ? ' ' : this.sums_.text) + "</div>";
    if (typeof this.sums_.title === "undefined" || this.sums_.title === "") {
      this.div_.title = this.cluster_.getMarkerClusterer().getTitle();
    } else {
      this.div_.title = this.sums_.title;
    }
    this.div_.style.display = "";
  }
  this.visible_ = true;
};

仍然,群集图标会有点弹性,因此要修复重写绘制函数的问题:

ClusterIcon.prototype.draw = function () {
  if (this.visible_) {
    var pos = this.getPosFromLatLng_(this.center_);
    this.div_.style.top = (pos.y + this.height_/2 - this.getImgSize() /2) + "px"; 
    this.div_.style.left = (pos.x + this.width_/2 - this.getImgSize() /2) + "px"; 
  }
};