13

Is there a method to change Z-indexes of layers in OpenLayers3 like it was in old version?

map.setLayerIndex(markers, 99); //set the marker layer to an arbitrarily high layer index

I need to change order of layers throughout using a map. So such possibility as defining z-index like this do not help

var geoLayer = new ol.layer.Vector({
    source : new ol.source.GeoJSON({
        projection : 'EPSG:900913',
        url : './myGeoJson.json'
    }),
    style : function(feature, resolution) {
        var text = resolution < 5000 ? feature.get('name') : '';
        if (!styleCache[text]) {
            styleCache[text] = [new ol.style.Style({
                fill : new ol.style.Fill({
                    color : 'rgba(255, 255, 255, 0.1)'
                }),
                stroke : new ol.style.Stroke({
                    color : '#319FD3',
                    width : 1
                }),
                text : new ol.style.Text({
                    font : '12px Calibri,sans-serif',
                    text : text,
                    fill : new ol.style.Fill({
                        color : '#000'
                    }),
                    stroke : new ol.style.Stroke({
                        color : '#fff',
                        width : 3
                    })
                }),
                zIndex : 999
            })];
        }

    }
});
  • I am having trouble using this solution, most likely due to my lack of understanding of such things. can you please post an example of the result, I believe it would really help me out? – dave_does_not_understand Dec 10 '14 at 17:23
10

Try something like:

map.getLayers().setAt(99, markers)

The list of layers is in an object inheriting from an ol.Collection. See the API doc for it.

Be careful, I'm pretty sure, you can't use arbitrary number like 99 in setAt: first arg is for the position in the array of layers and the second arg is for the layer element reference you want to move. To get number of layers, just use map.getLayers().getArray().length

Although you see we can get a JS array for layers, I'm not sure manipulating this array directly is the best way because layers can have events attached. You can use the ol.Collection methods instead.

  • I was looking for a solution for overlays, so I just wanted to add a comment saying that this (of course) also works for overlays, as map.getOverlays() returns an ol.Collection just like map.getLayers() does. – decibyte Jun 26 '18 at 8:11
7

It is not as easy as it used to be, but there are some helper methods for the collection. That should allow you to do similar things as ThomasG77 described above.

Assuming you have a map named map, with 4 layers i.e. [base_layer, coastlines, heatmap, markers]

Then you can get the collection via map.getLayers(), and the array of layers via map.getLayers().getArray(), and individual layers via

var heatmap = map.getLayers().getArray()[2]

You can manipulate the layer order via the collection methods. It will probably help to create some helper functions like:

function moveLayerBefore(map, old_idx, new_idx){
  var layer = map.getLayers().removeAt(old_idx);
  map.getLayers().insertAt(new_idx, layer);
}

Hopefully you have the ability to identify your layers and find them, I set an id on creation like layer.set("layer_id" 44), which can then be retrieved via layer.get("layer_id"). Then you can have a findLayer helper loop through your layer array and return the layer index.

function findLayer(map, layer_id){
  var layer_idx = -1;
  $.each(map.getLayers().getArray(), function (k,v){
    var this_layer_id = v.get("layer_id")
    if(this_layer_id == layer_id){
      layer_idx = k;
    }
  });
  return layer_idx;
}   

In this way I can have something like moveLayerBefore(map, findLayer(44), findLayer(22));

Anyway, there are a ton of methods in the collection, but hopefully this helps you get started. And sorry if there are bugs in that code, that is all mind compiled... :)

5

based on srussking answer I wrote the following code assuming the main map object called map and it is a global var, I preferred using find layer by name and not by id,

here is my code:

function moveLayerBefore(old_idx, new_idx){
    if((old_idx === -1) || (new_idx === -1)){
        return false;
    }

    layer = map.getLayers().removeAt(old_idx);
    map.getLayers().insertAt(new_idx, layer);
}

function findLayer(layer_name){
    var layer_idx = -1;
    $.each(map.getLayers().getArray(), function (k,v){
        var this_layer_name = v.get('name');
        if(this_layer_name == layer_name){
            layer_idx = k;
        }
    });

    return layer_idx;
}

// set name1 before name2
moveLayerBefore(findLayer('name1'),findLayer('name2'));
1

No need to handle the indices in the collection via setAt or insertAt. The easiest way is to use the setZIndex method on layer as in the API

geoLayer.setZIndex(999);
  • The tricky thing here is it seems to only work if the layers are already on the map. Say, I put two vector layers straight onto the map (one by one, not all at once). First one I set to ZIndex 10, second one to ZIndex 9. This does not work. The second one with ZIndex 9 will appear above ZIndex 10. – kiradotee Jan 24 '18 at 10:23
1

In my case ThomasG77's answer caused an AssertionError, because the layer that I was about to move to top was already attached to map (https://openlayers.org/en/v4.4.2/doc/errors/#58).

Solution that worked for me:

    let layers = map.getLayers();
    let markerTemp = layers.remove(refToMarkerLayer);
    layers.push(markerTemp);

(remove function returns removed layer). Oneliner should work as well, but I didn't test it.

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.