События Control.Layers

Механизм управления слоями в Leaflet построен вокруг связки объекта карты и экземпляра L.Control.Layers, который синхронизирует пользовательский интерфейс и состояние отображаемых слоёв. При взаимодействии с этим контролом библиотека генерирует набор событий, отражающих изменения в активных базовых слоях и наложениях.

События контроллера слоёв не изолированы внутри самого Control.Layers. Они пробрасываются на объект карты, что делает систему единообразной: обработка всегда выполняется через map.on(...), независимо от источника изменения.


Основные события Control.Layers

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

Связь Control.Layers и событий карты

Важно учитывать, что L.control.layers сам по себе не является источником событий в классическом смысле. Он изменяет состояние карты, а карта уже генерирует события. Это означает:

  • обработчики всегда регистрируются на map
  • невозможно «перехватить» события только внутри контроллера без карты
  • состояние слоёв всегда синхронизировано с внутренним стеком Leaflet

Пример комплексной обработки событий слоёв

Типичная структура работы с несколькими слоями включает базовую карту и набор оверлеев:

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 всегда отражает полное переключение контекста карты
  • оверлейные слои изменяют только визуальную надстройку, не затрагивая центр и zoom карты

Программное изменение слоёв и события

События 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 с карты не отключает уже добавленные слои и не останавливает генерацию событий, поскольку события принадлежат объекту карты. Контроллер влияет только на интерфейс управления, но не на жизненный цикл слоёв.


Взаимодействие с динамическими слоями GeoJSON

При использовании L.geoJSON события особенно полезны для управления тяжёлыми наборами данных:

const geoLayer = L.geoJSON(data);

map.on('overlayadd', function (e) {
    if (e.layer === geoLayer) {
        console.log('GeoJSON активирован');
    }
});

Сравнение по объекту слоя более надёжно, чем по имени, особенно при динамической генерации контролов.


Особенности повторного добавления слоёв

Если слой был удалён и добавлен повторно, события будут сгенерированы заново:

  • overlayremove при удалении
  • overlayadd при повторном добавлении

Leaflet не кэширует «состояние активности» слоя вне карты — оно определяется фактическим наличием слоя в текущем отображении.