События являются одним из ключевых механизмов взаимодействия пользователя с картой и объектами на ней. С их помощью реализуются реакции на действия пользователя, изменение состояния карты, загрузку данных, перемещение объектов и множество других сценариев.
В основе системы лежит объектная модель событий, позволяющая подписываться на определённые действия и выполнять произвольный код при их возникновении.
Практически все основные объекты Leaflet поддерживают механизм событий:
L.Map);L.Marker);L.Popup);Для регистрации обработчика используется метод on().
map.on('click', function(event) {
console.log(event);
});
После каждого щелчка по карте функция будет вызываться автоматически.
Сокращённая запись через стрелочную функцию:
map.on('click', (event) => {
console.log(event.latlng);
});
Каждый обработчик получает объект события, содержащий информацию о произошедшем действии.
Пример:
map.on('click', function(event) {
console.log(event.latlng);
});
Результат:
LatLng(55.75, 37.61)
Наиболее часто используемые свойства:
| Свойство | Описание |
|---|---|
latlng |
Географические координаты |
layerPoint |
Координаты относительно слоя |
containerPoint |
Координаты относительно контейнера карты |
target |
Объект, вызвавший событие |
sourceTarget |
Исходный источник события |
type |
Тип события |
Получение типа события:
map.on('click', function(event) {
console.log(event.type);
});
Вывод:
click
Один обработчик может обслуживать несколько событий.
map.on('click dblclick', function(event) {
console.log(event.type);
});
При клике:
click
При двойном клике:
dblclick
Leaflet позволяет регистрировать несколько обработчиков одной командой.
map.on({
click: function() {
console.log('Клик');
},
zoomend: function() {
console.log('Масштаб изменён');
},
moveend: function() {
console.log('Карта перемещена');
}
});
Такой подход делает код компактнее и удобнее при большом количестве событий.
Для удаления используется метод off().
Регистрация:
function handleClick(event) {
console.log(event.latlng);
}
map.on('click', handleClick);
Удаление:
map.off('click', handleClick);
После удаления функция больше не будет вызываться.
Метод once() позволяет выполнить код только один
раз.
map.once('click', function(event) {
console.log('Первый клик');
});
После первого срабатывания обработчик автоматически удаляется.
Полезно для:
Возникает при щелчке мышью по карте.
map.on('click', function(event) {
console.log(event.latlng);
});
Срабатывает при двойном клике.
map.on('dblclick', function() {
console.log('Двойной клик');
});
Возникает при нажатии правой кнопки мыши.
map.on('contextmenu', function(event) {
console.log(event.latlng);
});
Часто используется для создания собственных контекстных меню.
Нажатие кнопки мыши.
map.on('mousedown', function() {
console.log('Кнопка нажата');
});
Отпускание кнопки мыши.
map.on('mouseup', function() {
console.log('Кнопка отпущена');
});
Перемещение указателя по карте.
map.on('mousemove', function(event) {
console.log(event.latlng);
});
Применяется для:
Наведение и уход курсора.
map.on('mouseover', function() {
console.log('Курсор над картой');
});
map.on('mouseout', function() {
console.log('Курсор покинул карту');
});
Начало изменения масштаба.
map.on('zoomstart', function() {
console.log('Масштабирование началось');
});
Вызывается во время масштабирования.
map.on('zoom', function() {
console.log(map.getZoom());
});
Событие может срабатывать многократно.
Завершение масштабирования.
map.on('zoomend', function() {
console.log('Текущий масштаб:', map.getZoom());
});
Наиболее часто используемое событие из группы масштабирования.
Начало перемещения карты.
map.on('movestart', function() {
console.log('Перемещение началось');
});
Происходит во время движения.
map.on('move', function() {
console.log('Карта движется');
});
Из-за большого количества вызовов рекомендуется использовать осторожно.
Возникает после завершения движения.
map.on('moveend', function() {
const center = map.getCenter();
console.log(center);
});
Особенно полезно для динамической загрузки данных.
Типичный сценарий:
map.on('moveend', function() {
const bounds = map.getBounds();
loadData(bounds);
});
После изменения области просмотра загружаются только необходимые объекты.
Подобный подход используется во многих картографических сервисах.
Возникает после полной инициализации карты.
map.on('load', function() {
console.log('Карта готова');
});
Срабатывает перед уничтожением карты.
map.on('unload', function() {
console.log('Карта удаляется');
});
Полезно для освобождения ресурсов.
При добавлении и удалении слоёв генерируются специальные события.
map.on('layeradd', function(event) {
console.log(event.layer);
});
map.on('layerremove', function(event) {
console.log(event.layer);
});
Пример:
const marker = L.marker([55.75, 37.61]);
map.addLayer(marker);
После добавления будет вызван обработчик layeradd.
Маркеры поддерживают практически все события мыши.
const marker = L.marker([55.75, 37.61]).addTo(map);
Регистрация:
marker.on('click', function() {
console.log('Маркер выбран');
});
marker.on('click', function(event) {
console.log(
event.target.getLatLng()
);
});
marker.on('mouseover', function() {
this.setIcon(activeIcon);
});
marker.on('mouseout', function() {
this.setIcon(defaultIcon);
});
Подобный подход часто применяется для интерактивных карт объектов недвижимости, магазинов или туристических точек.
Для работы необходимо включить режим перетаскивания.
const marker = L.marker(
[55.75, 37.61],
{
draggable: true
}
).addTo(map);
Начало перетаскивания.
marker.on('dragstart', function() {
console.log('Начало перемещения');
});
Во время перемещения.
marker.on('drag', function(event) {
console.log(
event.target.getLatLng()
);
});
Завершение перетаскивания.
marker.on('dragend', function(event) {
const position =
event.target.getLatLng();
console.log(position);
});
Частое применение:
Всплывающие окна генерируют собственные события.
marker.bindPopup('Информация');
marker.on('popupopen', function() {
console.log('Окно открыто');
});
marker.on('popupclose', function() {
console.log('Окно закрыто');
});
Для подсказок (Tooltip) доступны аналогичные
обработчики.
marker.bindTooltip('Подсказка');
Открытие:
marker.on('tooltipopen', function() {
console.log('Подсказка открыта');
});
Закрытие:
marker.on('tooltipclose', function() {
console.log('Подсказка закрыта');
});
Все геометрические примитивы поддерживают обработчики событий.
Создание полигона:
const polygon = L.polygon([
[55.76, 37.60],
[55.74, 37.64],
[55.72, 37.58]
]).addTo(map);
Обработка клика:
polygon.on('click', function() {
console.log('Полигон выбран');
});
Частая практика при работе с геометрией.
polygon.on('mouseover', function() {
this.setStyle({
weight: 5
});
});
polygon.on('mouseout', function() {
this.setStyle({
weight: 2
});
});
Так создаётся визуальная реакция на действия пользователя.
Третий параметр метода on() задаёт контекст
выполнения.
const app = {
name: 'Map Application',
handleClick() {
console.log(this.name);
}
};
map.on(
'click',
app.handleClick,
app
);
Вывод:
Map Application
Без передачи контекста значение this было бы другим.
Leaflet позволяет создавать пользовательские события.
Отправка:
map.fire('dataLoaded');
Подписка:
map.on('dataLoaded', function() {
console.log('Данные загружены');
});
map.fire('userSelected', {
id: 25,
name: 'Москва'
});
Получение:
map.on('userSelected', function(event) {
console.log(event.id);
console.log(event.name);
});
Вывод:
25
Москва
Метод listens() позволяет определить, подписан ли объект
на событие.
if (map.listens('click')) {
console.log('Есть обработчики');
}
Подобная проверка используется внутри сложных компонентов и плагинов.
let marker;
map.on('click', function(event) {
if (marker) {
map.removeLayer(marker);
}
marker = L.marker(
event.latlng
).addTo(map);
});
После каждого щелчка старый маркер удаляется, а новый устанавливается в выбранную точку.
map.on('mousemove', function(event) {
document.getElementById('lat')
.textContent =
event.latlng.lat.toFixed(6);
document.getElementById('lng')
.textContent =
event.latlng.lng.toFixed(6);
});
Так реализуются панели текущих координат на картографических сервисах.
map.on('moveend', function() {
const bounds =
map.getBounds();
fetch('/api/objects', {
method: 'POST',
body: JSON.stringify({
north: bounds.getNorth(),
south: bounds.getSouth(),
east: bounds.getEast(),
west: bounds.getWest()
})
});
});
Сервер получает только текущую видимую область карты, что значительно снижает объём передаваемых данных и повышает производительность приложения.
Использование moveend вместо move
для загрузки данных
Событие move может вызываться десятки раз в секунду. Для
запросов к серверу обычно предпочтительнее moveend.
Удаление неиспользуемых обработчиков
При динамическом создании компонентов рекомендуется своевременно
вызывать off(), чтобы избежать утечек памяти.
Минимизация тяжёлых операций
Обработчики событий должны выполняться быстро. Длительные вычисления
во время mousemove, drag или zoom
могут привести к заметным задержкам интерфейса.
Разделение логики
Сложные обработчики желательно выносить в отдельные функции:
function updateData() {
console.log('Обновление данных');
}
map.on('moveend', updateData);
Так код становится проще поддерживать и тестировать.
Использование пользовательских событий
Собственные события позволяют организовывать слабосвязанную архитектуру, в которой различные части приложения взаимодействуют через механизм уведомлений, не зная внутренней реализации друг друга.