Search code examples
javascriptopenlayersopenlayers-3

How to select which feature overlay in case of overlapping or same geometry in OpenLayers


I created a map in which an overlay is opened clicking on the features. But I have problem if more than one feature are in overlapping, or worse, when features have the same geometry.

I use this code to show the overlay. But when two features have the same geometry only one overlay is shown.

const overlayContainerElement = document.querySelector('.overlay-container');

    const overlayLayer = new ol.Overlay ({
        element: overlayContainerElement
    });
    map.addOverlay(overlayLayer);
    const overlayFeatureName = document.getElementById('feature-name');
    const overlayFeatureAdditionalinfo = document.getElementById('feature-additionalinfo');


    map.on('click', function(e){
        overlayLayer.setPosition(undefined);
        map.forEachFeatureAtPixel(e.pixel, function (feature, layer){
            let clickedCoordinate = e.coordinate;
            let clickedFeatureName = feature.get('Number')
            let clickedFeatureInfo = feature.get('Text');
            overlayLayer.setPosition(clickedCoordinate);
            overlayFeatureName.innerHTML = clickedFeatureName;
            overlayFeatureAdditionalinfo.innerHTML = clickedFeatureInfo;
        },
        {
            layerFilter: function(layerCandidate){
                if (layerCandidate.get('title') === "Title") {
                    return 1;
                }
            }
        })
    });

Any idea how to configure a way in order to select which feature detail I want to see? So after clicking, if two features are under the mouse, a sort of list is shown to select what overlay I want to open.


Solution

  • Instead of updating your overlay inside the map.forEachFeatureAtPixel method, you could use the map.forEachFeatureAtPixel method to collect all features that were clicked, and then work with an Array of features.

    Something like this (untested / unfinished):

            var features = [];
            map.forEachFeatureAtPixel(e.pixel, function (feature, layer){
              features.push(feature);
            },
            {
                layerFilter: function(layerCandidate){
                    if (layerCandidate.get('title') === "Title") {
                        return 1;
                    }
                }
            });
    
            // And then, you could iterate on your features and show information as a list in your overlay.
    
            // todo - loop here
            /*
                let clickedCoordinate = e.coordinate;
                let clickedFeatureName = feature.get('Number')
                let clickedFeatureInfo = feature.get('Text');
                overlayLayer.setPosition(clickedCoordinate);
                overlayFeatureName.innerHTML = clickedFeatureName;
                overlayFeatureAdditionalinfo.innerHTML = clickedFeatureInfo;
            */
    

    You could have your overlay show a list of results in a "summary" fashion, and clicking on one of the feature name (for example) could show its full details within the overlay.

    HTH