6

I have a leaflet application where I have 4 layers that have many intersecting polygons such as, a counties layer, a school districts layer, a cities layer, and a layer of miscellaneous areas. All cities and miscellaneous areas physically intersect with counties and school districts. Some miscellaneous areas intersect with cities. I need "on" my click to get a popup that tells me the feature properties of each polygon at each layer - if that layer is indeed selected. I am having a terrible time working on a solution.

I love how I can loop over each layer in the leaflet L.featureGroup function. But I am stumped with querying each layer's features past that. I see the ._layer elements returned in the console. I suspect I need to detect intersections. Can someone point me in the right direction in terms of plugins and or leaflet methods.

3

This is not trivial, due to how web browsers handle DOM elements. If you have two (or more) overlapping (not nested) elements, pointer events will only apply to the top-most element. This is a limitation of the DOM model.

Two approaches to the problem spring to mind:

1 - Use GIS magic to calculate the intersection of all your different features. Create a feature layer with small polygons, each of which contains the properties of all your 4 feature layers.

i.e. each polygon should contain information about schools, counties, cities and misc; and each combination of schools, counties, cities and misc has its own polygon.

2 - Use something like Leaflet.CheapLayerAt to automate querying displayed vector data on the screen. When the user clicks on a feature on the map, remove that feature layer, run a Leaflet.CheapLayerAt query. That should return the feature from the underlying feature layer. Repeat this process until no more features are found, then re-add all the feature layers.

Yes, if you use this method you must remove and add layers. Or send them to the back of the stacking context so other layer is the top-most one when querying again.

2

Many Thanks to Ivan Sanchez for responding! I was really having tremendous problems trying to loop over each layer. It just wasn't behaving. So after much wrestling, the easiest solution was to abandon the loop and use the Leaflet PIP to query each layer at the click event. If the map "has" a layer then I used the Leaflet.PIP method - and pushed the results to a simple array. Finally, I was able to apply the data sitting in the array to a popup.

areas.on("click", function(event){
   popupOutput = [];
   var lng = event.latlng.lng;
   var lat = event.latlng.lat;
   var pipCountiesResults = leafletPip.pointInLayer([lng,lat], counties);
   var pipSchoolResults = leafletPip.pointInLayer([lng,lat], schools);
   var pipCitiesResults = leafletPip.pointInLayer([lng,lat], cities);
   var pipMiscResults = leafletPip.pointInLayer([lng,lat], misc);
     if(myMap.hasLayer(counties)){ 
            popupOutput.push(pipCountiesResults[0].feature.properties.NAMELSAD);    
     };
     if(myMap.hasLayer(schools)){
            popupOutput.push(pipSchoolResults[0].feature.properties.NAME);
     };
     if(myMap.hasLayer(cities) && pipCitiesResults != false){
            popupOutput.push(pipCitiesResults[0].feature.properties.NAMELSAD);
     };
     if(myMap.hasLayer(misc) && pipMiscResults != false){
            popupOutput.push(pipMiscResults[0].feature.properties.NAME);
     };
            popup.setLatLng(event.latlng)
                 .setContent(popupOutput + " You clicked the map at " 
                                 + event.latlng.toString())
                 .openOn(myMap); 
});

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

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