Проверка событий

В Leaflet система событий построена вокруг архитектуры подписки на события, возникающие у карты, слоёв и отдельных объектов. Каждый объект, наследующий L.Evented, способен регистрировать обработчики, удалять их и инициировать собственные события.

Основные механизмы работы:

  • регистрация обработчиков через on
  • одноразовые обработчики через once
  • удаление через off
  • генерация событий через fire

Каждое событие передаёт объект event, содержащий контекст произошедшего действия.


Регистрация и базовая проверка событий

Основной способ подключения логики к событиям — метод on.

map.on('click', function (e) {
    console.log('Клик по карте');
});

При каждом срабатывании события в обработчик передаётся объект события:

map.on('click', function (e) {
    console.log(e.type);      // click
    console.log(e.latlng);    // координаты клика
    console.log(e.containerPoint); // пиксельные координаты
});

Структура объекта события

Типичный объект события включает:

  • type — имя события
  • target — объект, вызвавший событие
  • latlng — географические координаты (для карты и маркеров)
  • layerPoint / containerPoint — координаты в пикселях
  • originalEvent — исходное DOM-событие

Проверка факта срабатывания событий

Контроль срабатывания событий обычно осуществляется через логирование и трассировку вызовов.

Логирование всех событий карты

function logEvent(e) {
    console.log('Event:', e.type, e);
}

map.on('click', logEvent);
map.on('zoomstart', logEvent);
map.on('zoomend', logEvent);
map.on('move', logEvent);
map.on('moveend', logEvent);

Такой подход позволяет отслеживать последовательность событий и их взаимосвязь.


Перехват и анализ событий карты

Leaflet генерирует множество системных событий карты:

События движения

  • movestart
  • move
  • moveend
map.on('moveend', function (e) {
    const center = map.getCenter();
    console.log('Новый центр:', center);
});

События масштаба

  • zoomstart
  • zoom
  • zoomend
map.on('zoomend', function () {
    console.log('Текущий zoom:', map.getZoom());
});

События загрузки

  • load
  • tileload
  • layeradd
map.on('load', function () {
    console.log('Карта полностью загружена');
});

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

Каждый слой в Leaflet также является источником событий.

Маркеры

const marker = L.marker([51.5, -0.09]).addTo(map);

marker.on('add', function () {
    console.log('Маркер добавлен на карту');
});

marker.on('remove', function () {
    console.log('Маркер удалён');
});

Попапы

marker.on('popupopen', function (e) {
    console.log('Попап открыт');
});

marker.on('popupclose', function () {
    console.log('Попап закрыт');
});

Векторные слои

const polygon = L.polygon([
    [51.51, -0.1],
    [51.49, -0.08],
    [51.5, -0.06]
]).addTo(map);

polygon.on('click', function (e) {
    console.log('Клик по полигону');
});

Контроль контекста события

Для анализа источника события используются свойства target и currentTarget.

map.on('click', function (e) {
    console.log(e.target); // карта
});

При работе с группами слоёв важно различать объект-источник:

group.on('click', function (e) {
    console.log('Источник события:', e.target);
});

Разница между target и source layer

В сложных слоях, таких как L.LayerGroup, событие может всплывать от вложенных объектов.

group.on('click', function (e) {
    console.log('Конечный источник:', e.propagatedFrom || e.target);
});

События могут проходить через цепочку вложенности, сохраняя информацию о первичном источнике.


Управление подписками и проверка активных обработчиков

Leaflet не предоставляет прямого публичного API для просмотра всех обработчиков, однако контроль осуществляется через управление ссылками на функции.

function handleClick(e) {
    console.log('click');
}

map.on('click', handleClick);

// проверка наличия логики достигается структурно
map.off('click', handleClick);

Ключевой принцип — идентичность ссылки на функцию.


Одноразовые события

Использование once позволяет автоматически удалить обработчик после первого срабатывания.

map.once('click', function (e) {
    console.log('Событие выполнится один раз');
});

Такой механизм используется для проверки первичного взаимодействия с картой или инициализации состояния.


Программная генерация событий

События могут быть инициированы вручную через fire, что позволяет тестировать логику обработки.

map.fire('click', {
    latlng: L.latLng(51.5, -0.09)
});

Это используется для проверки реакций системы без реального взаимодействия пользователя.


Фильтрация событий

Проверка событий часто реализуется через условные конструкции внутри обработчиков.

map.on('click', function (e) {
    if (!e.latlng) return;

    if (e.originalEvent.shiftKey) {
        console.log('Shift + click');
    }
});

Таким образом происходит разделение логики по условиям события.


Отладка событий через консоль

Для анализа поведения карты используется универсальный перехватчик:

map.on('*', function (type, e) {
    console.log(type, e);
});

Однако в Leaflet отсутствует встроенный wildcard, поэтому аналог реализуется через обёртку:

function attachLogger(map) {
    const events = ['click', 'move', 'zoom', 'zoomend', 'moveend'];

    events.forEach(eventName => {
        map.on(eventName, function (e) {
            console.log(eventName, e);
        });
    });
}

Всплытие и остановка распространения

Leaflet поддерживает механизм остановки распространения событий.

map.on('click', function (e) {
    L.DomEvent.stopPropagation(e.originalEvent);
});

Также применяется:

L.DomEvent.preventDefault(e.originalEvent);

Контроль распространения позволяет ограничивать влияние событий DOM и Leaflet одновременно.


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

Для глубокого анализа последовательности используется централизованный журнал событий.

const eventLog = [];

function traceEvent(e) {
    eventLog.push({
        type: e.type,
        time: Date.now(),
        latlng: e.latlng
    });
}

map.on('click move zoomend moveend', traceEvent);

Такая структура позволяет отслеживать динамику взаимодействия карты.


Связь DOM-событий и событий Leaflet

Каждое взаимодействие с картой начинается как DOM-событие и преобразуется Leaflet в собственный формат.

map.on('click', function (e) {
    console.log(e.originalEvent); // MouseEvent
});

Доступ к originalEvent используется для анализа клавиш модификации и состояния мыши.


Проверка цепочек событий

Некоторые действия вызывают последовательность событий:

  • click → mousedown → mouseup
  • dragstart → drag → dragend
  • zoomstart → zoom → zoomend
map.on('mousedown mouseup click', function (e) {
    console.log(e.type);
});

Анализ последовательности позволяет выявлять конфликтующие обработчики.


Изоляция и приоритет обработчиков

Порядок регистрации влияет на последовательность вызовов:

map.on('click', handlerA);
map.on('click', handlerB);

handlerA всегда выполняется раньше handlerB, если не изменён контекст выполнения через внутренние механизмы событий.


События пользовательских слоёв

При создании кастомных слоёв через L.Class или расширение L.Layer события можно генерировать вручную:

const CustomLayer = L.Layer.extend({
    onAdd: function (map) {
        this._map = map;
        this.fire('added');
    }
});

Проверка таких событий осуществляется через стандартную подписку:

layer.on('added', function () {
    console.log('Custom event fired');
});