7

I am doing an upgrade from OpenLayers 2 to Openlayers 3 and it seems to me that in OL3 there is no direct way to get a layer from map by its id. In OL2 it was like:

map.getLayer(id)

If we look in the OL3 API documentation and the ol.Map object, we would find only

map.getLayers()

which returns an ol.Collection. I could iterate through this collection with its forEach function and find the desired layer, but is this really the correct way? It seems a bit non-straightforward approach for such an essential and often needed purpose.

1
  • This does not take recursive groups into account
    – mihkelo
    Commented Oct 25, 2016 at 13:47

4 Answers 4

7

I finally made it with a little extension of the ol.Map object:

if (ol.Map.prototype.getLayer === undefined) {    
    ol.Map.prototype.getLayer = function (id) {
        var layer;
        this.getLayers().forEach(function (lyr) {
            if (id == lyr.get('id')) {
                layer = lyr;
            }            
        });
        return layer;
    }
}

This piece of code has to be executed after the OL3 library is loaded. As it uses only public functions of the ol.Map object, it is usable also with the compiled version of the OL3 library.

3
  • You can probably just do return lyr inside the if, and avoid var layer and return layer? A bit cleaner. Commented Nov 26, 2014 at 8:52
  • @JohnBarça return in the if would complete just the function inside the forEach loop, not the getLayer function.
    – meehocz
    Commented Nov 26, 2014 at 8:59
  • doh, never mind. Gets more coffee. Commented Nov 26, 2014 at 9:00
2

This is currently the case, see: https://github.com/openlayers/ol3/issues/2907 for the relevant discussion

1

As of ol3 recent versions, it's very easy to create a function that can be invoked whenever you need to grab a layer (whether in a group or not).

The other answers are fine as well, I only include this code here because of it's ease of adaptation for whatever you need, and being a newb once this type of snippet really helped me out- here's giving back to the community.

Best is to invoke a callback any place you need it:

function needMeSomeLayers () {

var layerArray = getAllofEm();

  layerArray.forEach(layer, function() {
    // do something with them
  })
}

where the function called:

function getAllofEm () {

var allLayers = [];

var mapLayers = map.getLayers().getArray();

mapLayers.forEach(function (layer, i) {
    if (layer instanceof ol.layer.Group && layer.getVisible() == true ) {
        layer.getLayers().getArray().forEach(function(sublayer, j, layers) {
            allLayers.push(sublayer);
        })
    } else if ( !(layer instanceof ol.layer.Group) && layer.getVisible() == true ) {
            allLayers.push(layer);
    }
});

return allLayers;
}

walks through all of the layers. In this example I test for visibility, but the

&& layer.getVisible

can be removed depending on cause, or used after the callback (in the forEach, for instance).

This is one of the most used utilities across all of the work I do with ol3, something that's great to have in the toolkit.

2
  • I'm confused about how the functions work together. As is, I get "layerArray is not defined". How do you get the layerArray in the scope of the function getAllofEm()?
    – user25976
    Commented Jun 8, 2019 at 0:30
  • 1
    @user25976 I'm pretty certain you caught a bug in the mock code, var mapLayers was incorrectly defined in the function getAllofEm(). Fixed. Commented Jun 9, 2019 at 2:50
0

The above solution works only without Groups. To recursively check layers you can use the following solution: extend the ol.map with recursive layer walker:

MyMap = function(opt_options) {

...

/**
 * gets layer of map by layer id
 * @method getLayerById
 * @param {number} layer_id the ID of the layer
 */
if(ol.Map.prototype.getLayerById == undefined)
this.getLayerById = function(layer_id) {
  var layer;
  MyMap.forEachLayerRecursive(this, function(lyr, idx, a) {
    if (lyr.get('id') === layer_id ) {
        layer = lyr;
    }
  });
  return layer;
};

ol.Map.call(this,options);

};

ol.inherits(MyMap, ol.Map);

MyMap.forEachLayerRecursive = function(layer, fn) {
  layer.getLayers().forEach(function(layer, idx, a) {
    fn(layer, idx, a);
    if (layer.getLayers) {
        ol.control.LayerSwitcher.forEachRecursive(layer, fn);
    }
 });

Then use it:

var baseMap = new MyMap();
var ls = baseMap.getLayerById('lid-123').getSource();

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.