Механизм управления слоями в Leaflet построен вокруг связки объекта
карты и экземпляра L.Control.Layers, который синхронизирует
пользовательский интерфейс и состояние отображаемых слоёв. При
взаимодействии с этим контролом библиотека генерирует набор событий,
отражающих изменения в активных базовых слоях и наложениях.
События контроллера слоёв не изолированы внутри самого
Control.Layers. Они пробрасываются на объект карты, что
делает систему единообразной: обработка всегда выполняется через
map.on(...), независимо от источника изменения.
baselayerchangeСобытие возникает при переключении базового слоя. Базовые слои в Leaflet предполагают взаимоисключающее отображение: одновременно активен только один слой из группы.
Структура события:
name — строка с именем активированного слояlayer — объект слоя (L.Layer), который был
включёнПример обработки:
map.on('baselayerchange', function (e) {
console.log('Активирован базовый слой:', e.name);
console.log('Объект слоя:', e.layer);
});
При срабатывании события предыдущий базовый слой автоматически отключается, и событие содержит только новый активный слой.
overlayaddСобытие вызывается при включении оверлейного слоя (накладываемого слоя), например маркеров, полигонов, heatmap или GeoJSON-слоёв.
Структура события:
name — имя добавленного слояlayer — объект включённого слояmap.on('overlayadd', function (e) {
console.log('Добавлен оверлей:', e.name);
});
Оверлейные слои не исключают друг друга, поэтому событие может вызываться многократно для разных слоёв без влияния на остальные.
overlayremoveСобытие противоположное overlayadd, возникает при
отключении оверлейного слоя.
Структура события:
name — имя удалённого слояlayer — объект слоя, который был отключёнmap.on('overlayremove', function (e) {
console.log('Удалён оверлей:', e.name);
});
Важно учитывать, что L.control.layers сам по себе не
является источником событий в классическом смысле. Он изменяет состояние
карты, а карта уже генерирует события. Это означает:
mapТипичная структура работы с несколькими слоями включает базовую карту и набор оверлеев:
const osm = L.tileLayer('https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png');
const satellite = L.tileLayer('https://{s}.tile.opentopomap.org/{z}/{x}/{y}.png');
const cities = L.layerGroup();
const rivers = L.layerGroup();
const map = L.map('map', {
center: [51.505, -0.09],
zoom: 5,
layers: [osm, cities]
});
const baseLayers = {
"OSM": osm,
"Satellite": satellite
};
const overlays = {
"Города": cities,
"Реки": rivers
};
L.control.layers(baseLayers, overlays).addTo(map);
map.on('baselayerchange', function (e) {
console.log('Базовый слой переключён:', e.name);
});
map.on('overlayadd', function (e) {
console.log('Оверлей включён:', e.name);
if (e.name === 'Города') {
console.log('Можно активировать дополнительную логику для городов');
}
});
map.on('overlayremove', function (e) {
console.log('Оверлей выключен:', e.name);
});
События слоёв тесно связаны с внутренним состоянием карты Leaflet. При их обработке важно учитывать следующие особенности:
baselayerchange
всегда отражает полное переключение контекста картыСобытия baselayerchange, overlayadd,
overlayremove вызываются не только при взаимодействии с
UI-контролом, но и при программном изменении состояния слоёв.
osm.addTo(map); // может инициировать baselayerchange
cities.addTo(map); // вызывает overlayadd
map.removeLayer(cities); // вызывает overlayremove
Таким образом, система событий остаётся единообразной вне зависимости от источника изменения: пользовательский интерфейс или код.
При работе с динамическими слоями важно учитывать, что события отражают уже изменённое состояние карты. Это означает:
overlayadd слой уже добавлен на
картуoverlayremove слой уже удалёнbaselayerchange новый базовый слой уже активенЭто позволяет использовать события не для «предсказания» изменений, а для реакции на них.
Leaflet допускает наличие нескольких экземпляров
L.control.layers, но события остаются глобальными
относительно карты. Если несколько контролов управляют одними и теми же
слоями, события не дублируются, поскольку они привязаны к слоям, а не к
контролу.
Синхронизация интерфейса:
map.on('baselayerchange', updateLegend);
Управление загрузкой данных:
map.on('overlayadd', function (e) {
if (e.name === 'Дороги') {
loadRoadData();
}
});
Очистка ресурсов:
map.on('overlayremove', function (e) {
if (e.name === 'Дороги') {
clearRoadData();
}
});
Имя слоя (name в событиях) берётся из объекта,
переданного в L.control.layers. Это строковый
идентификатор, который не связан с внутренним именем переменной
слоя.
const roads = L.layerGroup();
L.control.layers(null, {
"Дороги": roads
});
В событиях будет использоваться именно строка "Дороги",
а не roads.
Удаление Control.Layers с карты не отключает уже
добавленные слои и не останавливает генерацию событий, поскольку события
принадлежат объекту карты. Контроллер влияет только на интерфейс
управления, но не на жизненный цикл слоёв.
При использовании L.geoJSON события особенно полезны для
управления тяжёлыми наборами данных:
const geoLayer = L.geoJSON(data);
map.on('overlayadd', function (e) {
if (e.layer === geoLayer) {
console.log('GeoJSON активирован');
}
});
Сравнение по объекту слоя более надёжно, чем по имени, особенно при динамической генерации контролов.
Если слой был удалён и добавлен повторно, события будут сгенерированы заново:
overlayremove при удаленииoverlayadd при повторном добавленииLeaflet не кэширует «состояние активности» слоя вне карты — оно определяется фактическим наличием слоя в текущем отображении.