Z-индекс в OpenLayers 3: упорядочение слоев в OL3


13

Есть ли способ изменить Z-индексы слоев в OpenLayers3, как это было в старой версии?

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

Мне нужно изменить порядок слоев при использовании карты. Так что такая возможность, как определение z-index, не поможет

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
            })];
        }

    }
});

У меня возникли проблемы с использованием этого решения, скорее всего, из-за моего непонимания таких вещей. не могли бы вы опубликовать пример результата, я думаю, это действительно поможет мне?
dave_does_not_understand

Ответы:


10

Попробуйте что-то вроде:

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

Список слоев находится в объекте, наследуемом от ol.Collection. Смотрите API документацию для этого.

Будьте осторожны, я уверен, вы не можете использовать произвольное число, например, 99 в setAt: первый аргумент - это позиция в массиве слоев, а второй аргумент - это ссылка на элемент слоя, который вы хотите переместить. Чтобы получить количество слоев, просто используйтеmap.getLayers().getArray().length

Хотя вы видите, что мы можем получить массив JS для слоев, я не уверен, что манипулирование этим массивом напрямую - лучший способ, поскольку к слоям могут быть прикреплены события. Вы можете использовать ol.Collectionметоды вместо этого.


Я искал решение для оверлеев, поэтому я просто хотел добавить комментарий о том, что это (конечно) также работает для оверлеев, а map.getOverlays()возвращает так ol.Collectionже, как map.getLayers()делает.
Децибайт

8

Это не так просто, как раньше, но есть несколько вспомогательных методов для коллекции. Это должно позволить вам сделать то же самое, что и ThomasG77, описанный выше.

Предполагая, что у вас есть карта с именем map, с 4 слоями, т.е. [base_layer, coastlines, heatmap, маркеры]

Затем вы можете получить коллекцию через map.getLayers (), а массив слоев - через map.getLayers (). GetArray (), а отдельные слои - через.

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

Вы можете управлять порядком слоев с помощью методов сбора. Вероятно, это поможет создать некоторые вспомогательные функции, такие как:

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

Надеюсь, у вас есть возможность идентифицировать ваши слои и найти их, я устанавливаю идентификатор для создания, как layer.set ("layer_id" 44), который затем может быть получен через layer.get ("layer_id"). Затем вы можете создать вспомогательный цикл findLayer через массив слоев и вернуть индекс слоя.

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;
}   

Таким образом, у меня может быть что-то вроде moveLayerBefore (map, findLayer (44), findLayer (22));

В любом случае, в коллекции множество методов, но, надеюсь, это поможет вам начать работу. И извините, если в этом коде есть ошибки, все это скомпилировано ... :)


5

основываясь на ответе srussking, я написал следующий код, предполагая, что основной объект карты называется map, и это глобальная переменная, я предпочел использовать слой find по имени, а не по id,

вот мой код:

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

Нет необходимости обрабатывать индексы в коллекции через setAt или insertAt. Самый простой способ - использовать метод setZIndex на слое, как в API

geoLayer.setZIndex(999);

Хитрость здесь в том, что она работает, только если слои уже есть на карте. Скажем, я положил два векторных слоя прямо на карту (один за другим, не все сразу). Первый я установил на ZIndex 10, второй на ZIndex 9. Это не работает. Второй с ZIndex 9 появится над ZIndex 10.
kiradotee

1

В моем случае ответ ThomasG77 вызвал AssertionError, потому что слой, который я собирался переместить наверх, уже был прикреплен к карте ( https://openlayers.org/en/v4.4.2/doc/errors/#58 ).

Решение, которое сработало для меня:

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

(функция удаления возвращает удаленный слой). Онелинер тоже должен работать, но я этого не проверял.

Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.