В системе MapLibre GL JS масштабирование карты реализовано как часть
общей модели трансформации transform, где изменение zoom
влияет на вычисление тайлов, перерисовку слоёв и обновление геометрии на
canvas/WebGL. Все события, связанные с изменением масштаба, отражают
жизненный цикл этого процесса: начало взаимодействия, промежуточные
изменения и завершение анимации или пользовательского жеста.
Значение zoom в MapLibre GL JS — непрерывная величина (floating point), а не дискретный шаг. Это означает, что между целыми уровнями (например, 5 и 6) существуют промежуточные состояния:
Такой подход позволяет реализовать плавное масштабирование без «скачков» при смене тайлов.
Ключевые методы работы с масштабом:
map.getZoom(); // текущее значение zoom
map.setZoom(10); // установка масштаба
map.zoomTo(12); // с анимацией
map.easeTo({ zoom: 8 });
map.fitBounds(bounds);
MapLibre GL JS предоставляет несколько событий, связанных с изменением масштаба карты:
Срабатывает в момент начала изменения zoom, независимо от источника:
map.on('zoomstart', () => {
console.log('Начало изменения масштаба');
});
Особенность: событие вызывается один раз на цикл масштабирования, даже если внутри происходит множество промежуточных обновлений.
Событие непрерывного обновления масштаба.
map.on('zoom', () => {
console.log('Текущий zoom:', map.getZoom());
});
Характеристики:
Это событие критично для задач, требующих динамической реакции на масштаб: изменение размеров маркеров, адаптация UI, управление плотностью данных.
Срабатывает после завершения всех изменений масштаба.
map.on('zoomend', () => {
console.log('Масштабирование завершено:', map.getZoom());
});
Особенности:
Zoom может изменяться разными способами, и это влияет на характер событий.
wheel)В этом случае события zoom сопровождаются низкоуровневым событием:
map.on('wheel', (e) => {
// e.originalEvent содержит нативное событие колесика
});
Важно учитывать, что wheel не равен zoom, а
лишь может его инициировать.
map.zoomTo(14);
map.easeTo({ zoom: 9 });
map.setZoom(11);
Различие:
setZoom — мгновенное изменениеeaseTo — анимация с интерполяциейzoomTo — аналог easeTo с заданной цельюПри анимации генерируются все события жизненного цикла:
zoomstart → zoom → zoomend.
Zoom в MapLibre GL JS не изолирован — он является частью общей трансформации камеры. Поэтому при масштабировании также возникают события движения:
movestartmovemoveendПри изменении zoom без изменения центра (например, pinch на месте)
всё равно происходят move события, так как матрица
трансформации обновляется.
map.on('movestart', () => {
console.log('Начало движения/масштабирования');
});
map.on('zoomstart', () => {
console.log('Начало zoom');
});
map.on('zoom', () => {
const z = map.getZoom();
console.log('zoom:', z.toFixed(2));
});
map.on('zoomend', () => {
console.log('Завершение zoom:', map.getZoom());
});
map.on('moveend', () => {
console.log('Завершение трансформации карты');
});
Событие zoom может вызываться с высокой частотой (до 60
fps). Это требует аккуратного подхода к обработке:
Пример оптимизации:
let timeout;
map.on('zoom', () => {
clearTimeout(timeout);
timeout = setTimeout(() => {
console.log('Финальное значение zoom для логики:', map.getZoom());
}, 150);
});
Для синхронизации с рендер-циклом WebGL:
map.on('zoom', () => {
requestAnimationFrame(() => {
updateUI(map.getZoom());
});
});
Это позволяет избежать рассинхронизации между DOM и canvas.
Изменение zoom напрямую влияет на:
minzoom, maxzoom)Пример слоя с ограничением zoom:
map.addLayer({
id: 'cities',
type: 'circle',
source: 'points',
minzoom: 5,
maxzoom: 12
});
При выходе за диапазон слой перестаёт участвовать в рендере, даже если zoom событие продолжает происходить.
При завершении жестов MapLibre GL JS может продолжать движение камеры по инерции. В этом случае:
zoomend не вызывается до полной остановкиzoom продолжает обновлятьсяmoveend фиксирует завершение всей анимацииMapLibre GL JS поддерживает ограничения:
const map = new maplibregl.Map({
container: 'map',
style: 'style.json',
minZoom: 3,
maxZoom: 18
});
При достижении границ:
zoom могут продолжать вызываться в попытках
жестаZoom — лишь одна из составляющих камеры:
center — географическая позицияzoom — масштабbearing — поворотpitch — наклонИзменение любого из этих параметров может инициировать
move и рендер-пересчёт, но zoom дополнительно
влияет на выбор уровня тайлов и детализацию геометрии.
Типичный цикл масштабирования выглядит следующим образом:
zoomstartzoommovezoomendmoveendКаждый этап соответствует обновлению внутреннего состояния
transform и перерасчёту WebGL сцены.