Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to get a layer from a feature in Openlayers 3?

I can't find a way to go from a feature in a selection event to a layer that it may be a part of without traversing all the features of all my map layers, or storing an artificial layer ID within every feature at creation. Is this just not possible yet?

ol.js 3.7.0 ol.interaction.Selection -> click -> callback( event ){ event.selected[0] }

In another part of my app, I would like to go from the feature to the layer to determine the style being used on the feature, specifically whether or not it's visible.

ol.Feature.getStyle() || ol.Feature -> (layer?) -> getStyle()

like image 556
ryansstack Avatar asked Jul 08 '15 15:07

ryansstack


3 Answers

In OL 5.3.0, the Select interaction object has the getLayer() function to get the associated layer of the last selected feature. Example:

let selectClick = new Select({});
map.addInteraction(selectClick);

selectClick.on('select', function(e) {
    let featureSelected = e.selected[0];
    let layer = selectClick.getLayer(featureSelected);
    console.log(layer); // here you have the selected layer
});
like image 52
ahMarrone Avatar answered Oct 20 '22 19:10

ahMarrone


In Openlayers 4 - map.forEachFeatureAtPixel can be used to get at the parent layer of each feature.

See code snippet here: https://stackoverflow.com/a/50415743/2288488

like image 25
Rob Irwin Avatar answered Oct 20 '22 18:10

Rob Irwin


You could try with the filter function:

var select = new ol.interaction.Select({
    condition:  ...,
    filter: function(feature, layer){
        console.info(feature);
        console.info(layer.get('name'));
    }
});

UPDATE

I came up with this prototypied method, it does the job:

http://jsfiddle.net/jonataswalker/r242y7ke/

/**
 * This is a workaround.
 * Returns the associated layer.
 * @param {ol.Map} map.
 * @return {ol.layer.Vector} Layer.
 */
ol.Feature.prototype.getLayer = function(map) {
    var this_ = this, layer_, layersToLookFor = [];
    /**
     * Populates array layersToLookFor with only
     * layers that have features
     */
    var check = function(layer){
        var source = layer.getSource();
        if(source instanceof ol.source.Vector){
            var features = source.getFeatures();
            if(features.length > 0){
                layersToLookFor.push({
                    layer: layer,
                    features: features
                });
            }
        }
    };
    //loop through map layers
    map.getLayers().forEach(function(layer){
        if (layer instanceof ol.layer.Group) {
            layer.getLayers().forEach(check);
        } else {
            check(layer);
        }
    });
    layersToLookFor.forEach(function(obj){
        var found = obj.features.some(function(feature){
            return this_ === feature;
        });
        if(found){
            //this is the layer we want
            layer_ = obj.layer;
        }
    });
    return layer_;
};

select.on('select', function(evt){
    var feature = evt.selected[0];
    if(feature){
        var layer = feature.getLayer(map);

        console.info(layer.getStyle());
        console.info(layer.get('name'));
    }
});
like image 11
Jonatas Walker Avatar answered Oct 20 '22 19:10

Jonatas Walker