the_chimp
the_chimp

Reputation: 255

Leaflet - access specific polyline feature (GeoJSON)?

The situation: My web application shows a map with different trails of interest (my so called POIs) and a sidebar with information about each POI. Selecting a panel of the sidebar, the related POI should be selected/highlighted on the map.

Data and platforms used: I work with Leaflet and JavaScript, no jQuery. The data are added within Leaflet as GeoJSON. The trails are represented as polylines, but I call them POIs (just to clarify). I do not and cannot use jQuery.

What works: The trails (polylines) are added like this:

var pois = L.geoJson(pois, 
{
  style: style_pois,
  onEachFeature: onEachFeature
 });
 pois.addTo(map);

function onEachFeature(feature, layer)
{
layer.on('click', function (e)
{
    sidebar.open('pois');

    //get the ID of the clicked POI
    number = feature.properties.number;

    //Open the accordion tab
    var panel = document.getElementsByClassName('accordion-panel');
    panel[number-1].style.display="block";

    //highlight the selected POI
    var selectedFeature = e.target;
    selectedFeature.setStyle(style_pois_selected);
}); 
}

What does not work: Selecting a panel of the accordion, I get the ID of the related trail (polyline), but I cannot access and highlight this certain polyline feature within Leaflet.

This is the JavaScript code, where the accordion behavior is controlled:

var acc = document.getElementsByClassName('accordion');
var panel = document.getElementsByClassName('accordion-panel');

for (var i = 0; i < acc.length; i++) 
{
(function(index){
    acc[i].onclick = function()
    {           
        // Toggle between adding and removing the "active" class,
        //to highlight the button that controls the panel 
        this.classList.toggle("active");

        //Toggle between hiding and showing the active panel
        var panel = this.nextElementSibling;
        console.log("panel " + acc[0]);

        if (panel.style.display === "block") {
            panel.style.display = "none";
        } else {
            panel.style.display = "block";
        }
        var myIndex = index + 1;
        alert("INDEX " + myIndex);
    }
})(i);
}

Question: Is there a possibility, based on a layer that is included as GeoJSON in Leaflet to access a certain feature based on any property?

What I tried: I only came across solutions where the different behavior of a certain polyline is accessed within the onclick function. There it is easily possible to apply another color (setStyle). I need to access it from outside the layer. I already tried to again load the pois layer as I did above, just inside the accordion JavaScript and filter it for the certain ID so that only the one polyline is represented, but it only gave me an error that it is an invalid GeoJSON object (maybe a scope issue?).

I appreciate any help!

Upvotes: 3

Views: 2045

Answers (2)

the_chimp
the_chimp

Reputation: 255

For anyone who might come across the same problem - I found a solution.

I looked for hours to find out, if one can access a specific feature from a GeoJSON layer within Leaflet, but it seemed that there is no such method.

Although there is no official method for it, for me worked the following. When inside the accordion, one can just access the already loaded GeoJSON dataset, in my case pois and get the layer (this actually gets the feature, not the layer! a bit misleading) at the index position. For this one, a style can then be applied.

pois.getLayer(index).setStyle(style_pois)

To read out the index of the clicked accordion panel, I asked another question and was pointed in the right direction: Simple JavaScript accordion - how to get the index of the clicked panel?

Upvotes: 1

Camilo
Camilo

Reputation: 169

NOTE: I'd recommend you to set some JFiddle to reproduce your problem.

A solution I often use is to set the ID/Class property in each of the markers/points:

$.getJSON("data/displacement.geojson", function(data){
    pathsLayer = L.geoJson(data,{
        className: function(feature){ //Sets the class on element
            //Assuming your JSON has a property called ID
            return "ID-" + feature.properties.ID;
        },
        style: function (feature) {
            //If needed, you can also set style based on properties
        },
    })
});

After that you can set a global variable to keep record of the selection ID, and then use it to select and modify the specific element. Since Leaflet uses SVG elements, I recommend you to use D3.js to select/modify elements, for instance:

var selectedID = null; //Declare global variable

// You modify selectedID by actions on sidebar, e.g.:
selectedID = 001

d3.select(".ID-" + selectedID)
    .transition() //You can set easily transitions on attribute changes
    .duration(1000) // in ms
    .attr("attributeName", "attributeValue");

You can find an example here (although I know is a bit tricky to read using View Page Source (Ctrl + U))

Upvotes: 0

Related Questions