В библиотеке Leaflet обработка жестов построена вокруг системы обработчиков (handlers), привязанных к экземпляру карты. Каждый тип взаимодействия реализован как отдельный модуль, который может быть включён или отключён независимо.
Карта выступает центральным объектом, через который проходят все пользовательские действия: мышь, сенсорный экран, клавиатура. Внутри используется единая система событий, обеспечивающая согласованную модель поведения вне зависимости от устройства ввода.
Ключевая особенность архитектуры заключается в разделении:
Каждый жест реализуется через наследование от базового класса
обработчика L.Handler. Этот класс управляет жизненным
циклом взаимодействия:
addHooks);removeHooks).Типичный набор встроенных обработчиков карты:
dragging — перетаскивание карты;scrollWheelZoom — масштабирование колесом мыши;doubleClickZoom — масштабирование двойным кликом;boxZoom — масштабирование выделением области;keyboard — управление с клавиатуры;touchZoom — pinch-жесты на сенсорных экранах;tap — оптимизация тапа на мобильных устройствах.Каждый обработчик может быть включён или отключён через API карты:
map.dragging.enable();
map.scrollWheelZoom.disable();
Перетаскивание является основным способом навигации. Оно работает
через отслеживание последовательности событий
mousedown → mousemove → mouseup или их сенсорных
аналогов.
Внутренний процесс включает:
Поддерживается инерция, задаваемая параметрами карты:
inertiainertiaDecelerationinertiaMaxSpeedeaseLinearityИнерционное движение создаёт эффект «скольжения» после завершения жеста.
Обработчик scrollWheelZoom преобразует вращение колеса в
изменение zoom level.
Механизм включает:
Дополнительные параметры:
wheelDebounceTime — задержка между событиями;wheelPxPerZoomLevel — чувствительность.Жест pinch реализуется через обработчик touchZoom. Он
отслеживает одновременно несколько touch-точек и вычисляет расстояние
между ними.
Алгоритм:
Важный аспект — центр жеста, который вычисляется как середина между точками касания. Именно эта точка становится якорем масштабирования.
Мобильный обработчик tap оптимизирует поведение
одиночных касаний, устраняя задержку стандартного
click.
Двойной клик (doubleClickZoom) обрабатывается отдельно и
может:
Параметры:
doubleClickZoom: 'center' | 'around' | falseЖесты в Leaflet транслируются в высокоуровневые события карты.
mousedown, mouseup,
mousemovetouchstart, touchmove,
touchendclick, dblclickzoomstart, zoom, zoomendmovestart, move, moveenddragstart, drag, dragendЦепочка событий при перетаскивании:
mousedowndragstartdragdragendmoveendЦепочка масштабирования:
zoomstartzoomzoomendКаждое событие содержит контекст:
latlng);containerPoint);zoom).Поведение жестов настраивается через параметры при создании карты:
const map = L.map('map', {
dragging: true,
touchZoom: true,
scrollWheelZoom: true,
doubleClickZoom: true,
boxZoom: true,
keyboard: true
});
Дополнительные параметры:
tapTolerance — допустимое смещение при тапе;touchZoom — включение pinch-жестов;bounceAtZoomLimits — «отскок» на границах
масштабирования;worldCopyJump — логика перехода через границу
мира.Отключение жестов часто используется для статичных карт или встроенных мини-карт:
map.dragging.disable();
map.scrollWheelZoom.disable();
Внутренний модуль L.DomEvent обеспечивает
унифицированную работу с DOM-событиями.
Основные функции:
L.DomEvent.on(element, type, handler)L.DomEvent.off(element, type, handler)L.DomEvent.stopPropagation(e)L.DomEvent.preventDefault(e)Ключевая особенность — нормализация событий между браузерами и устройствами.
Также применяется система фильтрации событий:
При одновременном использовании нескольких типов ввода возникают конфликты:
Для их разрешения используется:
Пример: во время touchZoom блокируется
dragging, чтобы исключить смещение карты.
Также применяется механизм tap tolerance, который
различает клик и случайное смещение пальца.
Система L.Handler позволяет создавать собственные жесты,
интегрированные в жизненный цикл карты.
Структура кастомного обработчика:
L.CustomGesture = L.Handler.extend({
addHooks: function () {
L.DomEvent.on(this._map._container, 'pointerdown', this._onDown, this);
},
removeHooks: function () {
L.DomEvent.off(this._map._container, 'pointerdown', this._onDown, this);
},
_onDown: function (e) {
this._startPoint = e.clientX;
}
});
После создания обработчик подключается к карте:
map.addHandler('customGesture', L.CustomGesture);
map.customGesture.enable();
Подобный подход позволяет реализовать:
Жесты часто используются для синхронизации интерфейса с состоянием карты.
Примеры реакций:
movestart;moveend;zoomstart;zoom.map.on('movestart', () => {
// фиксация состояния интерфейса
});
map.on('moveend', () => {
// обновление данных по новому bbox
});
На мобильных устройствах поведение жестов отличается из-за особенностей сенсорного ввода:
Особое значение имеет параметр tap, который компенсирует
задержку click-событий в мобильных браузерах.
Жесты напрямую связаны с частотой перерисовки карты. Основные оптимизации:
move и zoom;requestAnimationFrame;При интенсивных жестах карта переиспользует уже загруженные тайлы, снижая нагрузку на сеть и рендеринг.
Также применяется разделение фаз: