События масштабирования

Масштабирование является одной из ключевых операций при работе с интерактивными картами. Пользователь может изменять уровень приближения с помощью колеса мыши, кнопок управления, жестов на сенсорных устройствах или программного вызова методов API. Для отслеживания таких действий Leaflet предоставляет набор специализированных событий, позволяющих реагировать на начало, процесс и завершение изменения масштаба.

События масштабирования используются для:

  • обновления пользовательского интерфейса;
  • загрузки данных в зависимости от уровня детализации;
  • управления отображением слоёв;
  • динамического изменения размеров объектов;
  • синхронизации нескольких карт;
  • выполнения аналитических операций после изменения масштаба.

Основные события масштабирования

Leaflet предоставляет три основных события:

Событие Описание
zoomstart Начало изменения масштаба
zoom Выполняется во время изменения масштаба
zoomend Завершение изменения масштаба

Все события регистрируются через метод on() объекта карты.

map.on('zoomstart', function() {
    console.log('Началось масштабирование');
});

map.on('zoom', function() {
    console.log('Масштаб изменяется');
});

map.on('zoomend', function() {
    console.log('Масштабирование завершено');
});

Событие zoomstart

Событие zoomstart возникает в момент начала изменения масштаба.

Оно срабатывает:

  • при вращении колеса мыши;
  • при двойном клике;
  • при использовании кнопок управления масштабом;
  • при программном вызове методов изменения масштаба;
  • при использовании жестов масштабирования на мобильных устройствах.

Пример:

map.on('zoomstart', function() {
    console.log('Текущий масштаб:', map.getZoom());
});

В момент вызова события масштаб карты ещё не изменился.

Это удобно для подготовки интерфейса к анимации:

map.on('zoomstart', function() {
    document.body.classList.add('zooming');
});

Событие zoom

Событие zoom вызывается многократно в процессе изменения масштаба.

При плавной анимации оно может срабатывать десятки раз за одну операцию масштабирования.

Пример:

map.on('zoom', function() {
    console.log('Масштаб:', map.getZoom());
});

Событие подходит для задач, требующих постоянного обновления состояния.

Например, отображение текущего уровня масштаба:

const zoomInfo = document.getElementById('zoom');

map.on('zoom', function() {
    zoomInfo.textContent = map.getZoom();
});

Событие zoomend

Событие zoomend возникает после полного завершения изменения масштаба.

Это наиболее часто используемое событие группы.

map.on('zoomend', function() {
    console.log('Новый масштаб:', map.getZoom());
});

Типичные сценарии применения:

  • подгрузка новых данных;
  • перестроение кластеров;
  • отображение дополнительных объектов;
  • изменение стилей слоёв;
  • запуск вычислений.

Пример загрузки данных после изменения масштаба:

map.on('zoomend', function() {
    loadDataForZoom(map.getZoom());
});

Использование zoomend предпочтительнее zoom, если операция является ресурсоёмкой.


Получение текущего масштаба

Для определения уровня приближения применяется метод getZoom().

let zoomLevel = map.getZoom();

console.log(zoomLevel);

Получение масштаба внутри обработчика:

map.on('zoomend', function() {
    let zoom = map.getZoom();

    console.log('Текущий масштаб:', zoom);
});

Изменение интерфейса в зависимости от масштаба

Многие приложения отображают различные элементы на разных уровнях приближения.

Пример:

map.on('zoomend', function() {

    if (map.getZoom() < 10) {
        console.log('Региональный уровень');
    } else {
        console.log('Городской уровень');
    }

});

Такой подход широко используется в ГИС-системах и картографических сервисах.


Управление видимостью слоёв

Часто определённые слои становятся полезными только на конкретных уровнях масштабирования.

Например, улицы отображаются только при сильном приближении.

map.on('zoomend', function() {

    if (map.getZoom() >= 15) {
        map.addLayer(streetsLayer);
    } else {
        map.removeLayer(streetsLayer);
    }

});

Другой пример:

map.on('zoomend', function() {

    const zoom = map.getZoom();

    if (zoom < 8) {
        map.addLayer(regionsLayer);
        map.removeLayer(buildingsLayer);
    } else {
        map.removeLayer(regionsLayer);
        map.addLayer(buildingsLayer);
    }

});

Реакция на конкретный уровень масштабирования

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

map.on('zoomend', function() {

    if (map.getZoom() === 18) {
        console.log('Максимальное приближение');
    }

});

Пример с диапазоном:

map.on('zoomend', function() {

    const zoom = map.getZoom();

    if (zoom >= 12 && zoom <= 15) {
        showDistrictInfo();
    }

});

Определение направления масштабирования

Leaflet не предоставляет отдельное событие увеличения или уменьшения масштаба, однако направление можно определить самостоятельно.

let previousZoom = map.getZoom();

map.on('zoomend', function() {

    let currentZoom = map.getZoom();

    if (currentZoom > previousZoom) {
        console.log('Приближение');
    }

    if (currentZoom < previousZoom) {
        console.log('Отдаление');
    }

    previousZoom = currentZoom;

});

Использование объекта события

Обработчики получают объект события.

map.on('zoomstart', function(event) {
    console.log(event);
});

Структура зависит от версии Leaflet и типа события.

На практике для получения актуального масштаба чаще используется сам объект карты:

map.on('zoomend', function(e) {
    console.log(map.getZoom());
});

События масштабирования и анимация

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

  1. Срабатывает zoomstart.
  2. Во время анимации многократно вызывается zoom.
  3. После завершения вызывается zoomend.
map.on('zoomstart', function() {
    console.log('Старт');
});

map.on('zoom', function() {
    console.log('Процесс');
});

map.on('zoomend', function() {
    console.log('Финиш');
});

Такой порядок сохраняется независимо от способа изменения масштаба.


Масштабирование через API

При программном изменении масштаба события также генерируются автоматически.

Пример:

map.setZoom(10);

Будут вызваны:

zoomstart
zoom
zoomend

Аналогично работают методы:

map.zoomIn();
map.zoomOut();
map.setZoom(15);
map.flyTo([55.75, 37.61], 12);

События при использовании flyTo

Метод flyTo() выполняет плавное перемещение и масштабирование.

map.flyTo(
    [55.75, 37.61],
    13
);

Во время выполнения могут возникать:

zoomstart
zoom
zoomend
movestart
move
moveend

Это позволяет отслеживать как изменение масштаба, так и изменение положения карты.


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

Во многих случаях карта одновременно перемещается и изменяет масштаб.

Для обработки обеих операций используются пары событий:

map.on('moveend', updateData);
map.on('zoomend', updateData);

Либо:

function updateData() {
    console.log('Обновление данных');
}

map.on('moveend', updateData);
map.on('zoomend', updateData);

Использование once для масштабирования

Если реакция требуется только один раз, применяется метод once().

map.once('zoomend', function() {
    console.log('Первое изменение масштаба');
});

После выполнения обработчик автоматически удаляется.


Удаление обработчиков

Удаление выполняется методом off().

function zoomHandler() {
    console.log('Масштаб изменён');
}

map.on('zoomend', zoomHandler);

Позже:

map.off('zoomend', zoomHandler);

Удаление всех обработчиков конкретного события:

map.off('zoomend');

Практический пример отображения масштаба

HTML:

<div id="map"></div>
<div id="info"></div>

Jav * aScript:

const info = document.getElementById('info');

function updateZoomInfo() {
    info.textContent =
        'Масштаб: ' + map.getZoom();
}

map.on('zoomend', updateZoomInfo);

updateZoomInfo();

После каждого изменения масштаба информация обновляется автоматически.


Практический пример динамического отображения маркеров

map.on('zoomend', function() {

    const zoom = map.getZoom();

    if (zoom >= 14) {
        map.addLayer(markerLayer);
    } else {
        map.removeLayer(markerLayer);
    }

});

При сильном приближении отображаются детальные объекты, а при удалении карты скрываются.


Практический пример подгрузки данных

map.on('zoomend', function() {

    const zoom = map.getZoom();

    fetch(`/api/data?zoom=${zoom}`)
        .then(response => response.json())
        .then(data => {
            updateMap(data);
        });

});

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


Рекомендации по использованию событий масштабирования

Для тяжёлых вычислений использовать zoomend.

map.on('zoomend', loadData);

Не выполнять дорогостоящие операции внутри zoom.

map.on('zoom', function() {
    // Только лёгкие действия
});

Хранить предыдущий масштаб для анализа направления изменения.

let previousZoom = map.getZoom();

Удалять ненужные обработчики.

map.off('zoomend', handler);

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

if (map.getZoom() >= 12) {
    map.addLayer(layer);
}

События zoomstart, zoom и zoomend образуют полный механизм контроля масштабирования в Leaflet, позволяя отслеживать начало операции, её выполнение и завершение, а также строить сложную логику управления картографическим интерфейсом в зависимости от текущего уровня приближения.