Архитектура слоёв в OpenLayers строится вокруг объекта карты, который хранит упорядоченную коллекцию слоёв и управляет их жизненным циклом. Каждый слой представляет собой отдельную визуальную или функциональную сущность: тайловую подложку, векторные данные, изображения, WMS/WMTS-источники или комбинированные отображения. Динамическое управление слоями заключается в изменении состава этой коллекции, параметров отдельных слоёв и их источников без пересоздания карты.
Все слои карты находятся в коллекции ol/Collection,
доступной через map.getLayers(). Эта коллекция поддерживает
реактивное поведение: изменения автоматически отражаются на карте.
Добавление слоя:
map.getLayers().push(tileLayer);
Удаление слоя:
map.getLayers().remove(tileLayer);
Поиск слоя в коллекции:
const layers = map.getLayers().getArray();
const target = layers.find(l => l.get('id') === 'roads');
Каждый слой можно идентифицировать через пользовательские свойства:
layer.set('id', 'roads-layer');
Вместо удаления слоя часто используется переключение видимости. Это дешевле с точки зрения производительности и сохраняет состояние слоя.
layer.setVisible(true);
layer.setVisible(false);
Состояние видимости учитывается при рендеринге, но слой остаётся в памяти и продолжает хранить источник данных.
Типичный сценарий — переключение тематических слоёв:
roadsLayer.setVisible(true);
buildingsLayer.setVisible(false);
waterLayer.setVisible(true);
Порядок отрисовки определяется свойством zIndex. Чем
выше значение, тем выше слой в визуальной иерархии.
roadsLayer.setZIndex(10);
buildingsLayer.setZIndex(5);
backgroundLayer.setZIndex(0);
При одинаковых значениях используется порядок добавления в коллекцию.
Практическое правило: базовые карты получают минимальный z-index, векторные данные — средний, интерактивные оверлеи — максимальный.
Одним из ключевых механизмов является замена source слоя
без пересоздания самого слоя.
const newSource = new ol.source.Vector({
url: 'data/upd ated.geojson',
format: new ol.format.GeoJSON()
});
vectorLayer.setSource(newSource);
Для тайловых слоёв:
tileLayer.setSource(new ol.source.XYZ({
url: 'https://tiles.example.com/{z}/{x}/{y}.png'
}));
Замена источника используется при переключении тематик, датасетов или серверов.
Некоторые источники поддерживают принудительное обновление:
vectorSource.refresh();
Для WMS:
wmsSource.updateParams({ time: Date.now() });
Для XYZ тайлов можно сбросить кэш:
tileSource.clear();
В реальных приложениях слои часто управляются через централизованное состояние (UI-фильтры, чекбоксы, маршруты отображения).
Пример синхронизации с UI:
function toggleLayer(id, visible) {
const layer = map.getLayers().getArray()
.find(l => l.get('id') === id);
if (layer) {
layer.setVisible(visible);
}
}
Для сложных проектов используется LayerGroup,
позволяющий управлять несколькими слоями как единым объектом.
const group = new ol.layer.Group({
layers: [roadsLayer, buildingsLayer]
});
map.getLayers().push(group);
Группу можно скрыть целиком:
group.setVisible(false);
Коллекция слоёв поддерживает события добавления и удаления:
map.getLayers().on('add', function (event) {
console.log('Добавлен слой:', event.element);
});
map.getLayers().on('remove', function (event) {
console.log('Удалён слой:', event.element);
});
Сами слои также генерируют события изменения состояния:
layer.on('change:visible', function () {
console.log('Изменена видимость слоя');
});
Векторные слои позволяют изменять отображаемые объекты без изменения источника.
Через стиль:
vectorLayer.setStyle(function (feature) {
return feature.get('population') > 1000
? bigCityStyle
: smallCityStyle;
});
Через фильтрацию данных:
vectorSource.forEachFeature(function (feature) {
feature.setStyle(
feature.get('active') ? activeStyle : null
);
});
Часто используется логика “наборов слоёв” — предопределённых конфигураций отображения карты.
function applyPreset(preset) {
map.getLayers().forEach(layer => {
layer.setVisible(false);
});
preset.layers.forEach(id => {
const layer = map.getLayers().getArray()
.find(l => l.get('id') === id);
if (layer) {
layer.setVisible(true);
}
});
}
Для оптимизации производительности слои создаются по требованию.
function ensureLayer(id) {
let layer = map.getLayers().getArray()
.find(l => l.get('id') === id);
if (!layer) {
layer = createHeavyLayer();
layer.se t('id', id);
map.getLayers().push(layer);
}
return layer;
}
Слои поддерживают изменение прозрачности без пересоздания:
layer.setOpacity(0.5);
Это позволяет накладывать данные и создавать композитные визуализации:
satelliteLayer.setOpacity(1.0);
labelsLayer.setOpacity(0.7);
heatmapLayer.setOpacity(0.6);
Некоторые слои активируются только в определённом диапазоне масштабов:
layer.setMinZoom(10);
layer.setMaxZoom(18);
Это снижает нагрузку на рендеринг и упрощает визуальную иерархию данных.
Слой может динамически менять тип отображения, сохраняя логическую идентичность.
Пример перехода от WMS к XYZ:
layer.setSource(new ol.source.XYZ({
url: 'https://tiles.example.com/{z}/{x}/{y}.png'
}));
Или от статического GeoJSON к кластеризованному:
layer.setSource(new ol.source.Cluster({
distance: 40,
source: vectorSource
}));
При сложных изменениях данных используется полная пересборка слоя:
map.getLayers().remove(layer);
layer = createLayer();
map.getLayers().push(layer);
Такой подход применяется, когда изменения затрагивают не только данные, но и логику рендеринга, стили или тип источника.
В сложных системах слои часто абстрагируются в отдельный менеджер:
class LayerManager {
constructor(map) {
this.map = map;
}
showOnly(ids) {
this.map.getLayers().forEach(l => {
l.setVisible(ids.includes(l.get('id')));
});
}
add(id, layer) {
layer.set('id', id);
this.map.getLayers().push(layer);
}
remove(id) {
const layer = this.map.getLayers().getArray()
.find(l => l.get('id') === id);
if (layer) {
this.map.getLayers().remove(layer);
}
}
}
Частые изменения слоёв могут приводить к перерасчёту рендера. Для оптимизации используется:
Особенно критичны операции с векторными слоями при больших объёмах данных, где каждое изменение стиля или источника может вызывать перерасчёт геометрии и перерисовку сцены.