3

How to highlight one feature on hover from a featureGroup layer?

It's easy when the layer is predefinied and static - I could write a highlighFeature and onEachFeature functions and pass them as options when creating a layer (like in the code created with qgis2web plugin).

But in my code I create line layer inside the code which creates point layer like this:

var linesFeatures = L.featureGroup();
var pointsLayer = L.geoJSON(points, {
    pane: 'pointsPane',
    pointToLayer: (feature, latlng) => {
        const div = document.createElement("div");
        div.innerHTML = `${feature.properties.name}<br>`;
    
        const button = document.createElement("button");
        button.innerHTML = "Create Line";
    
        button.onclick = function() {
            const line1 = L.polyline(
                [latlng, [10, 5]],
                {color: 'black',})
                .bindPopup(feature.properties.name);
                linesFeatures.addLayer(line1)
        };
    
        div.appendChild(button);
    
        return L.marker(latlng).bindPopup(div);
    }
    });
linesFeatures.addTo(map);

My first solution based on a highlightFeature from the code created with qgis2web plugin doesn't work and I don't know why:

function highlightFeature(e) {
    var layer = e.target;
    layer.setStyle({
        color: 'red'
    });
};
function resetHighlight(e) {
    var layer = e.target;
    layer.resetStyle(e.target);
};
function onEachFeature (feature, layer) {
    layer.on({mouseover: highlightFeature,
            mouseout: resetHighlight})
};

With these 3 functions above I add onEachFeature inside the code creating a line:

button.onclick = function() {
    const line1 = L.polyline(
        [latlng, [10, 5]],
        {color: 'black',
        onEachFeature: onEachFeature
        })
        .bindPopup(feature.properties.name);
        linesFeatures.addLayer(line1)
};

https://jsfiddle.net/nt284j9r/

My second solution with layer.on method works partially, because I want to highlight only a one line on hover and it makes to change color of all the lines from the lines layer. I don't know how to write to make it highlight only one line. I was trying to change var layer to the var feature and passing it as an argument byt it didn' work.

linesFeatures.on('mouseover', function(e) {
    var layer = e.target;
    layer.setStyle({color: 'green'});
});

linesFeatures.on('mouseout', function(e) {
    var layer = e.target;
    layer.setStyle({color: 'red'});
});

https://jsfiddle.net/hsc6n2am/1/

1 Answer 1

3

Your first solution doesn't work because L.polyline has no such thing as onEachFeature option.

Your second solution highlights all polylines because you attach events to linesFeatures group layer which contains all the lines.

Solution is to attach events to individual lines while they are created. Since linesFeatures layer is general group layer, not GeoJSON layer, it does not have .resetStyle method to reset member's layer style. One possible solution for this is to store default line style in some custom property (let's say defaultStyle) with name that's not in conflict with standard Leaflet properties.

Code could then look something like this:

function highlightFeature(e) {
  var layer = e.target;
  layer.setStyle({
    color: 'red'
  });
};
function resetHighlight(e) {
  var layer = e.target;
  layer.setStyle(layer.defaultStyle);
};

var linesFeatures = L.featureGroup();
var pointsLayer = L.geoJSON(points, {
  pointToLayer: (feature, latlng) => {
    const div = document.createElement("div");
    div.innerHTML = `${feature.properties.name}<br>`;

    const button = document.createElement("button");
    button.innerHTML = "Create Line";

    button.onclick = function() {
      var lineStyle = {color: 'black'}
      const line1 = L.polyline(
        [latlng, [10, 5]],
        lineStyle
      ).bindPopup(feature.properties.name);
      line1.defaultStyle = lineStyle;
      line1.on({
        mouseover: highlightFeature,
        mouseout: resetHighlight
      });
      linesFeatures.addLayer(line1);
    };

    div.appendChild(button);

    return L.marker(latlng).bindPopup(div);
  }
}).addTo(map);
linesFeatures.addTo(map);  
1
  • I knew onEachFeature may not work with line layer but I showed how I was trying to solve this problem. The same with featureGroup, I knew that it containes all the lines and that’s why it highlights all the lines. But I didn’t think to add the code when creating lines. Anyway I wouldn’t come up witch such a solution as I’m learning Leaflet in this project. Thanks a lot!
    – Maryla
    Jan 7, 2023 at 22:01

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.