Leaflet предоставляет модуль управления слоями через
Control.Layers, предназначенный для переключения между
базовыми картографическими подложками и дополнительными слоями
(оверлеями). Этот компонент решает задачу динамического включения и
отключения визуальных слоёв карты без необходимости пересоздавать сам
объект карты.
L.control.layers представляет собой UI-контрол, который
отображается поверх карты и содержит:
Базовая идея заключается в разделении всех слоёв на две категории:
Base Layers
Overlays
Базовая инициализация выполняется через передачу объектов:
const osm = L.tileLayer('https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png', {
attribution: '© OpenStreetMap contributors'
});
const satellite = L.tileLayer('https://{s}.tile.opentopomap.org/{z}/{x}/{y}.png', {
attribution: '© OpenTopoMap contributors'
});
const cities = L.layerGroup();
const rivers = L.layerGroup();
const baseMaps = {
"OpenStreetMap": osm,
"Satellite": satellite
};
const overlays = {
"Города": cities,
"Реки": rivers
};
const map = L.map('map', {
center: [51.1694, 71.4491],
zoom: 5,
layers: [osm, cities]
});
L.control.layers(baseMaps, overlays).addTo(map);
Base layers реализуются как взаимоисключающие переключатели. При выборе нового слоя происходит:
Особенность заключается в том, что Control.Layers не
хранит копии слоёв, а управляет ссылками на уже созданные объекты.
Overlays функционируют независимо друг от друга. Каждый слой:
Пример добавления слоя GeoJSON:
const geojsonLayer = L.geoJSON(data, {
style: {
color: "blue",
weight: 2
}
});
geojsonLayer.addTo(map);
L.control.layers(baseMaps, {
"Границы": geojsonLayer
}).addTo(map);
Control.Layers поддерживает добавление новых слоёв после создания:
const control = L.control.layers(baseMaps, overlays).addTo(map);
const parks = L.layerGroup();
control.addOverlay(parks, "Парки");
Также возможно добавление базового слоя:
const terrain = L.tileLayer('https://{s}.tile.stamen.com/terrain/{z}/{x}/{y}.jpg');
control.addBaseLayer(terrain, "Terrain");
Удаление выполняется через соответствующие методы:
control.removeLayer(parks);
control.removeLayer(terrain);
Важно: удаление из Control.Layers не удаляет слой с
карты автоматически. Управление отображением остаётся отдельной
задачей:
map.removeLayer(parks);
Конфигурация контроллера включает ряд параметров:
L.control.layers(baseMaps, overlays, {
collapsed: true,
position: 'topright',
autoZIndex: false
}).addTo(map);
true — контрол свернут по умолчанию;false — список всегда раскрыт.Используется для управления плотностью интерфейса.
Определяет расположение контроллера:
toplefttoprightbottomleftbottomrightЕсли включено (true), Leaflet автоматически управляет
z-index слоёв при переключении base layers. Это полезно при
использовании тайловых слоёв, но может мешать при сложной кастомной
композиции.
Control.Layers влияет только на отображение элементов
интерфейса, но не на порядок отрисовки напрямую. Порядок слоёв
контролируется:
pane-механизмом;bringToFront() и bringToBack().Пример:
markers.addTo(map).bringToFront();
Для сложных проектов используется L.layerGroup или
L.featureGroup:
const citiesGroup = L.layerGroup([city1, city2, city3]);
const roadsGroup = L.layerGroup([road1, road2]);
L.control.layers(baseMaps, {
"Города": citiesGroup,
"Дороги": roadsGroup
}).addTo(map);
FeatureGroup дополнительно поддерживает события и
вычисления границ:
const group = L.featureGroup([marker1, marker2]);
map.fitBounds(group.getBounds());
Контроллер генерирует события при взаимодействии:
map.on('overlayadd', function (e) {
console.log('Добавлен слой:', e.name);
});
map.on('overlayremove', function (e) {
console.log('Удалён слой:', e.name);
});
map.on('baselayerchange', function (e) {
console.log('Активный базовый слой:', e.name);
});
Структура объекта события:
name — имя слоя;layer — объект слоя.Контрол можно модифицировать через CSS:
.leaflet-control-layers {
font-size: 13px;
background: #fff;
border-radius: 6px;
}
.leaflet-control-layers-expanded {
padding: 10px;
}
Дополнительно можно создавать кастомные контролы на основе
L.Control, если стандартный интерфейс недостаточен.
Control.Layers хранит ссылки на слои в приватных
структурах, но доступ к ним возможен косвенно через добавление и
удаление:
const control = L.control.layers(baseMaps, overlays);
control.addTo(map);
control.addOverlay(L.marker([0, 0]), "Новая точка");
Прямое чтение внутренних списков не предусмотрено API.
При работе с потоковыми или обновляемыми данными слои часто пересоздаются:
function updateGeoJSON(data) {
if (map.hasLayer(geojsonLayer)) {
map.removeLayer(geojsonLayer);
control.removeLayer(geojsonLayer);
}
geojsonLayer = L.geoJSON(data);
control.addOverlay(geojsonLayer, "Данные");
geojsonLayer.addTo(map);
}
Хотя интерфейс допускает несколько base layers в объекте, активным всегда остаётся только один. Leaflet гарантирует:
Control.Layers одинаково работает с:
L.tileLayerL.imageOverlayL.geoJSONL.layerGroupПример image overlay:
const image = L.imageOverlay('map.png', bounds);
L.control.layers(baseMaps, {
"Изображение": image
}).addTo(map);
При десятках и сотнях слоёв интерфейс может становиться перегруженным. Используются подходы:
const categories = {
"Инфраструктура": infraGroup,
"Природа": natureGroup
};
При вызове map.remove() контрол также уничтожается, но
слои остаются в памяти, если не удалены явно. Это важно при
SPA-приложениях, где карта пересоздаётся многократно.
Control.Layers не хранит состояние UI как источник
истины. Источник состояния — сама карта:
map.hasLayer(layer)map.addLayer(layer)map.removeLayer(layer)Контрол лишь отражает текущее состояние.
if (!map.hasLayer(parks)) {
map.addLayer(parks);
}