mwallisch
mwallisch

Reputation: 1810

Leaflet path: how can I set a css class?

Well the title says it all but here is some code so you see what i mean.

function eachFeature(feature, layer) {
     layer.on({
         mouseover: highlightFeature,
         mouseout: resetHighlight,
     });
}
geojson = L.geoJson(geojson_raw, { style: style, onEachFeature: eachFeature });
geojson.addTo(map);

geojson_raw is the geojson object which is held in a javascript variable. style is just the function that returns an object with some style attributes. highlightFeature / resetHighlight are functions to change these styles according to mousein/out events.

So this code works and I already know how to change styles by reacting on user events. But how can I set an actual css-classname on the paths that are created from my geojson data? Later in my code I would like to select paths by a specific classname.

UPDATE

2 years later I stumbled over this issue once again. And it took me 2 hours to solve the mystery. The accepted answer below does work, BUT there is a catch. It only works if you set the cssClass before you call addTo(map) on the layer. After finally digging it up in the source code it became clear that leaflet only sets the cssClass when each path gets initialised.

Upvotes: 17

Views: 17231

Answers (7)

René K
René K

Reputation: 396

If the GeoJSON layer has already been added to the map then the following solution worked for me:

leafletGeoJSONLayer.eachLayer(function (layer) {
  let container = layer._path;
  container.classList.add("your-css-class");    
});

If the css identifier is already used by leaflet (e.g. cursor) you should add !important to the css key value pair.

Upvotes: 0

David Calhoun
David Calhoun

Reputation: 8581

Something like this should do the trick. feature._container exposes the underlying DOM element, so you can use regular DOM operations on it (e.g. classList on modern browsers, or setAttribute('class', 'someClass') in older browsers).

function eachFeature(feature, layer) {
     // Need to use setTimeout hack so the DOM container will be
     // available.  WARNING: may cause race condition issues,
     // maybe tie into some other timing event?
     window.setTimeout(function() {
         feature._container && feature._container.classList.add('someClass');
     }, 0);
}
geojson = L.geoJson(geojson_raw, { onEachFeature: eachFeature });
geojson.addTo(map);

Upvotes: 0

jean-baptiste
jean-baptiste

Reputation: 714

Using Leaflet 1.x, here is a slightly different way to do this - in my case the map was already initialized, so the className styling mentioned above did not work.

function eachFeature(feature, layer) {
     layer.on({
         mouseover: function(e) {$(e.target.getElement()).addClass("active");},
         mouseout: function(e) {$(e.target.getElement()).removeClass("active");}
     });
}

You can also set the class attribute directly using setAttribute on e.target.getElement() if you're not using jQuery.

Upvotes: 1

Mr. Concolato
Mr. Concolato

Reputation: 2230

The code below will allow you to add a class after the paths are created by the geoJosn method with D3.

var svg = d3.select(map.getPanes().overlayPane).append("svg"),
g = svg.append("g").attr("class", "your_class");

However, if you want to add them on creation using only leaflet, try returning them in the style(feature) method like this:

function style(feature) {
        return {
          weight: 1,
          opacity: .5,
          fillOpacity: 0.7,
          className: feature.properties.name_of_node
        };
}

That worked really well for me.

Upvotes: 13

the_web
the_web

Reputation: 406

You can either add a "className" attribute to your style object, or add the class later like this:

function eachFeature(feature, layer) {
     layer.on({
         mouseover: highlightFeature,
         mouseout: resetHighlight,
     });
}
geojson = L.geoJson(geojson_raw, { style: style, onEachFeature: eachFeature });
geojson.setStyle({'className': 'map-path'}); //will add the required class
geojson.addTo(map);

Upvotes: 4

hugo der hungrige
hugo der hungrige

Reputation: 12912

Expanding on @tbicr s answer, you should be able to do something like this:

function onEachFeature(feature, path) {
  path.on('click', addClass);
}

function addClass(e){
    var path = e.target;
    var container = path._container;
    $(container).attr('class', 'test');
}

geojson = L.geoJson(geojson_raw, { style: style, onEachFeature: eachFeature });
geojson.addTo(map);

EDIT: As always, I would be glad flor an explanation, if you decide to downvote, so I can improve it. This is the only answer so far, which describes how to add a class dynamically in detail and I can't see whats wrong with it.

Upvotes: -1

tbicr
tbicr

Reputation: 26070

If you use SVG, then you can get container as this._container and update it class.

If you use Canvas, then there are will be problems, because canvas drowning don't support DOM styles and drawing with content.

So you can't use styles with different implementations and better use styles.

Upvotes: -1

Related Questions