0

In a Leaflet map, when a school point is clicked it passes an id of that school and adds a student point layer specific to that school. The point layer is rendered on the map as marker cluster. So, clicking on another school will add student marker specific to that second school and so on. I want to display student marker cluster of each school with different colors.

Marker Cluster is defined as below:

 var mcStudent= L.markerClusterGroup({
                spiderfyOnMaxZoom: true,
                disableClusteringAtZoom: 14,
                maxClusterRadius: 5,
                spiderfyDistanceMultiplier:10,            
                iconCreateFunction: function(cluster) {
                    var markers = cluster.getAllChildMarkers();
                    var html = markers.length;
                    $('<style>.stdCluster {background-color:'+bgcolor+';}</style>').appendTo('head'); //override class attribute (background color)
                     return new L.DivIcon({ html: html, className: 'stdCluster', iconSize: new L.Point(15, 15) });

                     }            

                });

The button calls a function loadStudent() which is defined as below:

var student;
var bgcolor;
 
function loadStudent(id){
    bgcolor = '#'+(Math.random()*0xFFFFFF<<0).toString(16); //generate color code dynamically
    $.ajax({
            url:'php/findStudent.php', 
            type:'POST',
            data:{id:id},
            success: callbackStd
    });
    
           
    function callbackStd(response){                    
        student = L.geoJSON(JSON.parse(response), {pointToLayer:function(feature,latlng){        
            return mcStudent.addLayer(L.marker(latlng,{icon: studentIcon}));  
        }});
        

    student.addTo(mymap);
            
};

The issue is: marker cluster color changes dynamically as expected but it applies for all school student point clusters. For example, when a first school student point is loaded, the cluster icon color looks like below: enter image description here When second school point is added. it changes the color for both first and second school: enter image description here Now, when third school student point is added, it changes the color of all 3 schools. enter image description here I want to display student marker cluster of each school with different color. I could not work out the logic here.

4
  • 1
    It's not exactly clear what you want to achieve here. Marker cluster stands for bunch of markers, but you seem to be trying to set different marker cluster color with each marker added. Please clarify this, some pictures would help.
    – TomazicM
    Jun 28, 2023 at 20:17
  • Yes you are right. When I click on a schoolA it loads its student data which will be clustered until zoom level 14 and will have a random color (say green). When I click on another schoolB it loads student data of that school. It applies a new color to SchoolB student cluster (say pink). Problem is when SchoolB students are loaded, color of SchoolA student cluster will also change to the same color as that of School B i.e. Pink. Maybe I need to create new cluster for each school, but not sure how to do that. Appreciate your assistance. Jun 30, 2023 at 5:24
  • It's a bit clearer now. But to achieve what you want to achieve, you should have separate cluster layer for each school. Is that so at the moment? If you have the same cluster layer for all schools, sooner al alter when you zoom out enough, students from different schools will be shown in the same cluster icon.
    – TomazicM
    Jul 4, 2023 at 8:24
  • That is why I tried using array so that each school can have separate marker cluster. Roughly it is like this: var mcStudent=[], var n=0, then mcStudent[n] = L.markerClusterGroup({........}) then increment the number n=n+1 inside the loadStudent function. But, somehow it did not work. I need to dig bit further. Jul 5, 2023 at 6:58

1 Answer 1

0

To achieve what you want to achieve, you should have separate cluster layer for each school. Create random color for each cluster and use it in iconCreateFunction option function for that cluster.

Below is an example of how code could look then. regions is GeoJSON with four polygons where random points are created. number property of points feature is for test just sequential number.

var tiles = L.tileLayer('https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png', {
  maxZoom: 18,
  attribution: '&copy; <a href="https://www.openstreetmap.org/copyright">OpenStreetMap</a> contributors'
}),
latlng = L.latLng(46, 15);

var map = L.map('map', {center: latlng, zoom: 8, layers: [tiles]});

function createCluster() {
  var bgcolor = '#'+(Math.random()*0xFFFFFF<<0).toString(16);
  var markers = L.markerClusterGroup({
    spiderfyOnMaxZoom: true,
    disableClusteringAtZoom: 14,
    maxClusterRadius: 5,
    spiderfyDistanceMultiplier:10,            
    iconCreateFunction: function (cluster) {
      console.log(cluster);
      var markers = cluster.getAllChildMarkers();
      var n = 0;
      for (var i = 0; i < markers.length; i++) {
        n += markers[i].number;
      }
      var html = '<div style="background-color: ' + bgcolor + '">' + n + '</div>';
      return L.divIcon({
        html: html,
        className: 'mycluster',
        iconSize: L.point(60, 30)
      });
    },
    spiderfyOnMaxZoom: false, showCoverageOnHover: false, zoomToBoundsOnClick: false
  });
  return(markers);
}

regions.features.forEach(function(region) {
  var bbox = turf.bbox(region);
  var points = turf.randomPoint(80, {bbox: bbox});
  var markerCluster = createCluster();
  var n = 0;
  L.geoJSON(points, {
    onEachFeature: function(feature, layer) {
      layer.number = ++n;
      markerCluster.addLayers(layer);
    }
  });
  map.addLayer(markerCluster);
});

The above code gives this result:

enter image description here

4
  • this is not exactly what I wanted. I have edited the questions and added some images to clarify the questions. Jul 4, 2023 at 2:11
  • I also tried using array like: var mcStudent=[], var n=0, then mcStudent[n] = L.markerClusterGroup({........}) then increment the number n=n+1 inside the loadStudent function. It did not work. Jul 4, 2023 at 2:22
  • See modified answer.
    – TomazicM
    Jul 5, 2023 at 9:16
  • Thanks @TomazicM. This works but I had to modified the code to match my requirement though. Since we are styling html content to show different colors; now it shows both the cluster icon and html content just like in the screenshot you posted. So, I applied same styling to html as that of class stdCluster and made the L.divIcon() bit smaller so that the html completely overlaps the icon. Cheers, it did fulfill my requirement. Jul 7, 2023 at 2:12

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.