Механизм событий в Leaflet построен на модели подписки/оповещения, где практически любой объект (карта, слой, маркер, геометрия) может генерировать и обрабатывать события. Мышиные события являются одним из центральных элементов взаимодействия, поскольку обеспечивают связь между действиями пользователя и географическими объектами.
События мыши распространяются как на контейнер карты, так и на отдельные векторные и растровые слои, при этом поведение зависит от типа слоя, его опций и уровня вложенности в дерево слоёв.
Leaflet использует унифицированный набор DOM-событий, которые пробрасываются через собственную систему событий:
click — одиночный кликdblclick — двойной кликmousedown — нажатие кнопки мышиmouseup — отпускание кнопки мышиmouseover — наведение курсораmouseout — уход курсораmousemove — перемещение курсораcontextmenu — вызов контекстного меню (правый
клик)Эти события доступны как для карты, так и для интерактивных слоёв (markers, polylines, polygons, GeoJSON-объекты).
Каждое событие в Leaflet передаёт объект с расширенной информацией:
latlng — географические координаты точки событияlayerPoint — координаты относительно слояcontainerPoint — координаты относительно контейнера
картыoriginalEvent — исходное DOM-событие браузераtarget — объект, на котором произошло событиеtype — тип событияПример обработки:
map.on('click', function (e) {
console.log(e.latlng);
console.log(e.containerPoint);
console.log(e.originalEvent);
});
Карта является глобальным объектом, который принимает события независимо от наличия слоёв.
map.on('click', function (e) {
console.log('Клик по карте:', e.latlng);
});
map.on('mousemove', function (e) {
console.log('Движение мыши:', e.latlng);
});
Особенности:
mousemove вызывается очень часто и требует
оптимизацииclick зависит от точности определения интерактивного
слояВекторные слои (маркер, линия, полигон) имеют собственную обработку событий.
const marker = L.marker([51.5, -0.09]).addTo(map);
marker.on('click', function (e) {
console.log('Клик по маркеру');
});
const polygon = L.polygon([
[51.51, -0.08],
[51.5, -0.06],
[51.52, -0.05]
]).addTo(map);
polygon.on('mouseover', function () {
console.log('Наведение на полигон');
});
const polyline = L.polyline([
[51.5, -0.1],
[51.52, -0.12]
]).addTo(map);
polyline.on('click', function (e) {
console.log(e.latlng);
});
Для обработки мышиных событий слой должен быть интерактивным. Это регулируется опцией:
const circle = L.circle([51.508, -0.11], {
radius: 500,
interactive: true
}).addTo(map);
При отключённой интерактивности события мыши не срабатывают, даже если объект визуально присутствует.
Leaflet поддерживает всплытие событий от слоя к карте.
Пример:
map.on('click', function () {
console.log('Клик по карте');
});
marker.on('click', function () {
console.log('Клик по маркеру');
});
При клике на маркер событие может быть обработано и маркером, и картой.
Контроль поведения:
marker.on('click', function (e) {
L.DomEvent.stopPropagation(e);
});
Для тонкой настройки используется L.DomEvent:
L.DomEvent.stopPropagation(e);
L.DomEvent.preventDefault(e);
marker.on('click', function (e) {
L.DomEvent.stopPropagation(e);
L.DomEvent.preventDefault(e);
});
const polygon = L.polygon(coords).addTo(map);
polygon.on('mouseover', function () {
polygon.setStyle({ color: 'red' });
});
polygon.on('mouseout', function () {
polygon.setStyle({ color: 'blue' });
});
Механизм drag основан на мышиных событиях:
const marker = L.marker([51.5, -0.09], {
draggable: true
}).addTo(map);
marker.on('dragstart', function () {
console.log('Начало перетаскивания');
});
marker.on('drag', function (e) {
console.log(e.latlng);
});
marker.on('dragend', function () {
console.log('Конец перетаскивания');
});
map.on('mousemove', function (e) {
const lat = e.latlng.lat;
const lng = e.latlng.lng;
});
Также доступны экранные координаты:
map.on('mousemove', function (e) {
console.log(e.containerPoint);
});
mousemove и производительностьСобытие mousemove генерируется с высокой частотой, что
требует оптимизации обработки.
Типичный подход — троттлинг:
let lastTime = 0;
map.on('mousemove', function (e) {
const now = Date.now();
if (now - lastTime < 50) return;
lastTime = now;
console.log(e.latlng);
});
map.on('contextmenu', function (e) {
console.log('Правый клик:', e.latlng);
});
Подавление стандартного меню браузера:
map.on('contextmenu', function (e) {
L.DomEvent.preventDefault(e.originalEvent);
});
При использовании GeoJSON события назначаются через
onEachFeature:
L.geoJSON(data, {
onEachFeature: function (feature, layer) {
layer.on('click', function (e) {
console.log(feature.properties.name);
});
layer.on('mouseover', function () {
layer.setStyle({ weight: 5 });
});
layer.on('mouseout', function () {
layer.setStyle({ weight: 2 });
});
}
}).addTo(map);
Карта может перехватывать события, даже если они произошли на слоях:
map.on('click', function (e) {
console.log('Глобальный обработчик:', e.latlng);
});
При необходимости можно различать источник:
map.on('click', function (e) {
if (e.originalEvent) {
console.log('DOM-событие');
}
});
mouseover
и mouseoutЭти события чувствительны к пересечению границ объектов и могут вызываться многократно при сложной геометрии.
Особенности:
Пример стабилизации:
let hovered = false;
polygon.on('mouseover', function () {
if (hovered) return;
hovered = true;
polygon.setStyle({ color: 'green' });
});
polygon.on('mouseout', function () {
hovered = false;
polygon.setStyle({ color: 'blue' });
});
При наложении объектов события могут перехватываться верхним слоем. Управление осуществляется через:
paneinteractiveПример управления слоями:
const pane = map.createPane('topPane');
pane.style.zIndex = 650;
L.circle([51.5, -0.09], {
pane: 'topPane'
}).addTo(map);
mousemove без ограниченийstopPropagation при конфликте слоёвoriginalEvent, приводящее к потере
контекста DOMЧасто мышиные события используются вместе для построения логики рисования или редактирования:
map.on('mousedown', startDraw);
map.on('mousemove', updateDraw);
map.on('mouseup', finishDraw);
Такая схема формирует базу для кастомных инструментов редактирования геометрии и интерактивных картографических редакторов.