Markerclusterer set marker cluster icon depending on markers inside it

Novarg picture Novarg · Dec 9, 2014 · Viewed 8.8k times · Source

Let's say that I want to make a webpage that will show approximate number of free parking spots left on each parking(due to confidentiality I'm not allowed to give any details of what I'm actually doing). For this I'm using Google maps and Markerclusterer. So for parking with less than 5% spots left I'd like to show a red marker, for parkings with 5%-25% spots I'd show a yellow one and for ones with more than 25% free spots I want to make it green. So far I could make those markers and cluster them, but here's the tricky part(and question itself):

How can I make a cluster icon dependant on the markers inside it?

For example:

  • Parking A is green
  • Parking B is red
  • Parking C is green
  • Parking D is yellow

When zoomed out I want to show the cluster that has all 4 of them red(worst of all). When zoomed in I'd get 2 clusters(A+B and C+D). I want the first cluster(A+B) to be red and second(C+D) should be yellow.

What I did so far:

var mcOptions = {gridSize: 50, maxZoom: 15, styles: [{
    height: 46,
    url: "///Users/Novarg/Downloads/foundation-5.4.7/img/greenC.png",
    width: 46
  },
  {
    height: 46,
    url: "///Users/Novarg/Downloads/foundation-5.4.7/img/redC.png",
    width: 46
  }]};
  var markers = [];
  for (var i = 0; i < 100; i++) {
    var latLng = new google.maps.LatLng(51 + Math.random(),
      4 + Math.random());
    var marker = new google.maps.Marker({'position': latLng, icon: 'img/greenP.png'});
    markers.push(marker);
  }
  for (var i = 0; i < 20; i++) {
    var latLng = new google.maps.LatLng(51 - Math.random(),
      4 - Math.random());
    var marker = new google.maps.Marker({'position': latLng, icon: 'img/redP.png'});
    markers.push(marker);
  }
  var markerCluster = new MarkerClusterer(map, markers, mcOptions);
}
google.maps.event.addDomListener(window, 'load', initialize);

Right now I only have red and green markers, which should be enough to test it. But behaviour of this cluster now is as follows:

  • All clusters with less than 10 markers in it are green
  • All clusters with more than 9 markers in it are red

EDIT

From this link I found that what I might need is Calculator. So I tried it, but still no luck(although I think that I'm getting closer. Actually, I hope I'm very close to the solution right now).

So I tried to change my options:

var mcOptions = {gridSize: 50, maxZoom: 15, styles: [{
  height: 46,
  url: "///Users/Novarg/Downloads/foundation-5.4.7/img/greenC.png",
  width: 46
},
{
  height: 46,
  url: "///Users/Novarg/Downloads/foundation-5.4.7/img/redC.png",
  width: 46
}],
calculator: function(markers, numStyles) {
  for (var i = 0; i < markers.length; i++) {
    if (markers[i].getIcon().indexOf("redP.png") > -1) {
      return {text: markers.length, index: 1};
    }
  }
  return {text: markers.length, index: 0};
}
};

But the Calculator is never being used. I tested it by putting a simple alert('test'); inside it.

I hope this additional info will help you to help me find a solution.

Answer

Novarg picture Novarg · Dec 10, 2014

As I already mentioned in the edit, I was very close to the solution. So I took another(fresh) look at the code today, checked the docs once again and noticed the following in the ClusterIconInfo:

index number The index plus 1 of the element in the styles array to be used to style the cluster icon.

So basically I solved this problem simply by incrementing the index by one(and I also moved Calculator to be a var and then used setCalculator() method on the MarkerClusterer itself). So my code became:

var calc = function(markers, numStyles) {
  for (var i = 0; i < markers.length; i++) {
    if (markers[i].getIcon().indexOf("redP") > -1) {
      return {text: markers.length, index: 2};
    }
  }
  return {text: markers.length, index: 1};
}

var mcOptions = {gridSize: 50, maxZoom: 15, styles: [{
    height: 46,
    url: "img/greenC.png",
    width: 46
  },
  {
    height: 46,
    url: "img/redC.png",
    width: 46
  }]
};

var markerCluster = new MarkerClusterer(map, markers, mcOptions);
markerCluster.setCalculator(calc);

And now it works like a charm(as it should).

Hopefully this could help somebody someday.