Search code examples
javascriptleafletmarkerclusterer

Leaflet cluster color based on icons inside


I have pins on my leaflet.js map where the image is determined by the status of the object they are representing. For example, online and offline users - online are green and offline are red. I do this by adding a class to the divIcon and then control the images with css.

I have now added marker clustering to my map. What I want to do is determine the color of the cluster by the majority of status' within the cluster. My first idea was to do something like this:

this.markers = L.markerClusterGroup({
    iconCreateFunction: function(cluster) {
        // Use this somehow to filter through and look at the pin elements
        console.log(cluster.getAllChildMarkers());

        return new L.DivIcon({ html: /* ?? */ });
    }
});

But unfortunately I am not able to access the HTML elements from the array returned from getAllChildMarkers.

Anyone have any ideas on how I might be able to do this? Or a way to get the pin's HTML element?

Thanks

EDIT:

Here is where I create my map pins (assigned to my backbone model's mapPin attribute):

that.mapPins.org = L.divIcon({
className: 'org-div-icon',
    html: "<div class='org-status "+ org.getGroupStatus() +"'></div>",
    iconSize: [35, 35],
    iconAnchor: [18, 17]
});

And here is how I change the class dynamically:

$(model.get('mapPin')._icon).find('.org-status').attr('class', 'org-status ' + model.getGroupStatus());

I thought that I would be able to access _icon from the return of getAllChildMarkers like I do above, but it doesn't seem to be there.


Solution

  • You can use getAllChildMarkers to get all of the markers in the cluster. Once you have a marker, you can access its class with marker.options.icon.options.className. You can access the html with marker.options.icon.options.html

    Here's some code that uses underscore.js functions to count the number of markers with each class, find the one that's most popular, and use that class for the cluster marker.

    var markers = L.markerClusterGroup({
      iconCreateFunction: function (cluster) {
        var childMarkers = cluster.getAllChildMarkers();
        // count how many there are of each class
        var counts = _.countBy(childMarkers, function(marker) {
          // class at icon level
          //return marker.options.icon.options.className;
          // class inside html
          return $(marker.options.icon.options.html).attr('class');
        });
        // get the class with the highest count
        var maxClass = _.invert(counts)[_.max(counts)];
        // use this class in the cluster marker
        return L.divIcon({ html: cluster.getChildCount(), className: maxClass });
      },
    });