Search code examples
javascriptsvgleafletgeojson

Dynamic Leaflet layer class


This is my scenario: I have a geojson with point features, some with the attribute "ambulance", other "intervention". I will add them on the map with pointToLayer

var geojsonLayer = L.geoJson(cars, {
pointToLayer: function(feature, latlng) {
    return new L.Marker(latlng, {icon: cssIcon});
    }, onEachFeature: onEachFeature });

the cssIcon variable enables me to use SVG for my points.

var cssIcon = L.divIcon({
      className: "css-icon",
      html: "<svg> my svg code here </svg>"
      ,iconSize: [20,20]
      ,iconAnchor: [20,20]});

Now the problem. I need to add specific classes (based on the features attributes) to this Svgs so I can animate them using the new Web Animation Api. I have tried the following:

function onEachFeature(feature, layer) {
layer.on({
    add: addClass,
})};

... where the addClass function should query the feature, check if the feature's attribute is either "ambulance" or "intervention" and add a class accordingly:

function addClass(e){
    var layer = e.target;
    if(layer.feature.properties.car_type === "ambulance"){
    L.DomUtil.addClass(layer.defaultOptions.icon.options, "ambulance-class");

}else(layer.feature.properties.car_type === "intervention") {
    L.DomUtil.addClass(layer.defaultOptions.icon.options, "intervention-class");
}};

What I get is :

  • the layers with the "ambulance" attribute will get the "ambulance-class" class, but ...
  • the layers with the "intervention" attribute will get the "intervention-class" and will also get the "ambulance-class" class.

I also tried:

 geojson_layer.eachLayer(function (layer) {  
  if(layer.feature.properties.car_type === "ambulance") {    
    L.DomUtil.addClass(layer.defaultOptions.icon.options, "ambulance-class"); 
  }});

..but this won't add classes at all. I might be wrong in using layer.defaultOptions.icon.options to add the class, but using this I am able to get the object with document.getElementsByClassName("ambulance-class"). Any ideas?


Solution

  • If you call a separate function to create your icon within pointToLayer, you can check the feature properties and append the appropriate class to className there:

    function getCssIcon(feature) {
      if (feature.properties.car_type === "ambulance") {
        classTxt = " ambulance-class";
      } else if (feature.properties.car_type === "intervention") {
        classTxt = " intervention-class";
      }
      return L.divIcon({
        className: "css-icon" + classTxt,
        html: "<svg> my svg code here </svg>",
        iconSize: [20, 20],
        iconAnchor: [20, 20]
      });
    }
    
    var geojsonLayer = L.geoJson(cars, {
      pointToLayer: function(feature, latlng) {
        return new L.Marker(latlng, {
          icon: getCssIcon(feature)
        });
      },
      onEachFeature: onEachFeature
    }).addTo(map);