В Leaflet взаимодействие с картой на сенсорных устройствах строится на сочетании нативных DOM-событий браузера и внутренней системы событий карты. Сенсорный ввод не рассматривается как отдельный слой логики: он трансформируется в унифицированные события карты, аналогичные кликам и перемещениям мыши.
Ключевая особенность модели — абстрагирование различий между мышью и касанием. Один и тот же обработчик может реагировать на взаимодействие независимо от устройства ввода, при этом объект события содержит расширенные данные о координатах и контексте.
Основные принципы обработки касаний:
L.Map);latlng;originalEvent.Leaflet предоставляет набор опций, влияющих на поведение касаний. Они задаются при создании карты или изменяются через методы управления состоянием.
Пример конфигурации:
const map = L.map('map', {
center: [51.505, -0.09],
zoom: 13,
touchZoom: true,
tap: true,
doubleClickZoom: true,
bounceAtZoomLimits: true
});
Отключение сенсорного поведения используется в случаях, когда поверх карты располагаются сложные интерфейсы жестов или кастомные обработчики:
map.touchZoom.disable();
map.doubleClickZoom.disable();
map.tap?.disable();
Leaflet проксирует низкоуровневые touch-события в систему событий карты. Основные из них:
Срабатывает при первом касании поверхности карты.
map.on('touchstart', function (e) {
console.log('Начало касания', e);
});
Срабатывает при завершении касания.
map.on('touchend', function (e) {
console.log('Окончание касания');
});
Генерируется при перемещении пальца по экрану.
map.on('touchmove', function (e) {
console.log('Движение касания');
});
Эти события полезны при реализации кастомных жестов, рисования на карте и анализа поведения пользователя.
Leaflet преобразует касания в высокоуровневые события, которые одинаково работают на десктопе и мобильных устройствах.
Срабатывает после завершения короткого касания или клика мышью.
map.on('click', function (e) {
console.log(e.latlng);
});
Двойное касание или двойной клик.
map.on('dblclick', function (e) {
console.log('Двойное взаимодействие', e.latlng);
});
На сенсорных устройствах могут соответствовать началу и завершению касания в упрощённой форме.
map.on('mousedown', () => console.log('Нажатие'));
map.on('mouseup', () => console.log('Отпускание'));
Каждое событие Leaflet содержит унифицированную структуру данных.
Пример анализа события:
map.on('touchstart', function (e) {
const coords = e.latlng;
const screenPoint = e.containerPoint;
const nativeEvent = e.originalEvent;
console.log(coords, screenPoint, nativeEvent.touches);
});
Масштабирование реализуется через встроенный механизм
touchZoom. Он преобразует расстояние между пальцами в
изменение уровня зума карты.
При включённой опции:
const map = L.map('map', {
touchZoom: true
});
Leaflet автоматически:
Отключение:
map.touchZoom.disable();
Leaflet не предоставляет отдельного события long press, но его можно
реализовать через комбинацию touchstart и
touchend.
let pressTimer;
map.on('touchstart', function (e) {
pressTimer = setTimeout(() => {
console.log('Долгое нажатие', e.latlng);
}, 600);
});
map.on('touchend', function () {
clearTimeout(pressTimer);
});
Такой подход используется для:
Поведение событий зависит от устройства, но Leaflet стремится минимизировать различия.
Перетаскивание (dragging) тесно связано с touchmove.
map.on('dragstart', () => {
console.log('Начало перемещения карты');
});
map.on('drag', () => {
console.log('Перемещение');
});
map.on('dragend', () => {
console.log('Окончание перемещения');
});
На сенсорных устройствах drag активируется при:
При работе с картой внутри мобильных интерфейсов возникает конфликт между прокруткой страницы и жестами карты.
Leaflet решает его следующим образом:
preventDefault() внутри обработчиков.Дополнительная настройка:
const map = L.map('map', {
dragging: true,
touchZoom: true,
scrollWheelZoom: true
});
Сенсорные события генерируются с высокой частотой, особенно
touchmove. Избыточная логика внутри обработчиков может
снижать плавность взаимодействия.
Типовые подходы оптимизации:
touchmove;requestAnimationFrame.Пример ограничения частоты:
let lastRun = 0;
map.on('touchmove', function (e) {
const now = Date.now();
if (now - lastRun < 50) return;
lastRun = now;
console.log(e.latlng);
});
Сенсорные события часто применяются для создания специализированных инструментов поверх карты.
const points = [];
map.on('touchmove', function (e) {
points.push(e.latlng);
});
map.on('click', function (e) {
L.marker(e.latlng).addTo(map);
});
map.on('touchstart', function (e) {
L.circle(e.latlng, { radius: 50 }).addTo(map);
});
Хотя Leaflet абстрагирует сложные жесты, исходные данные доступны
через originalEvent.touches.
map.on('touchstart', function (e) {
const touches = e.originalEvent.touches;
console.log('Количество касаний:', touches.length);
});
Это позволяет реализовать:
При отключении touchZoom и связанных опций:
map.touchZoom.disable();
map.dragging.disable();
Такая конфигурация применяется в статичных картах и встраиваемых мини-картах без интерактивности.