Google Maps JavaScript API построен вокруг событийной модели, в которой взаимодействие пользователя с картой, а также изменения состояния карты, экспонируются через систему слушателей. Архитектура событий основана на паттерне Observer: объекты карты и её компонентов генерируют события, а код приложения регистрирует обработчики, реагирующие на эти события.
События в API делятся на несколько категорий:
Система событий реализована через объект
google.maps.event и методы экземпляров, таких как
addListener.
Ключевой принцип:
Каждый объект карты может быть источником событий, а любой обработчик может быть подписан на эти события.
Базовый механизм подписки реализуется через метод:
google.maps.event.addListener(instance, eventName, handler);
или через сокращённую форму:
instance.addListener(eventName, handler);
map.addListener("click", (event) => {
console.log("Координаты клика:", event.latLng.lat(), event.latLng.lng());
});
Объект event содержит контекст события, включая
географические координаты latLng.
clickСрабатывает при клике по карте. Передаёт объект
MouseEvent, содержащий координаты.
map.addListener("click", (e) => {
const position = {
lat: e.latLng.lat(),
lng: e.latLng.lng()
};
});
bounds_changedГенерируется при изменении границ видимой области карты.
map.addListener("bounds_changed", () => {
const bounds = map.getBounds();
});
zoom_changedСрабатывает при изменении масштаба:
map.addListener("zoom_changed", () => {
console.log("Zoom:", map.getZoom());
});
center_changedВызывается при изменении центра карты:
map.addListener("center_changed", () => {
const center = map.getCenter();
});
Маркер является одним из наиболее часто используемых источников событий.
marker.addListener("click", () => {
console.log("Маркер нажат");
});
Если включена опция draggable: true, доступны
события:
marker.addListener("dragstart", () => {
console.log("Начало перетаскивания");
});
marker.addListener("drag", () => {
console.log("Перетаскивание");
});
marker.addListener("dragend", (e) => {
console.log("Финальная позиция:", e.latLng);
});
Наряду с методами экземпляров используется глобальный объект:
google.maps.event.addListener(map, "click", handler);
Также доступны дополнительные функции:
addListenerOnce — одноразовый обработчикremoveListener — удаление подпискиclearInstanceListeners — очистка всех слушателей
объектаgoogle.maps.event.addListenerOnce(map, "idle", () => {
console.log("Карта впервые стабилизировалась");
});
Событие idle возникает, когда карта завершила все
визуальные обновления.
Каждый зарегистрированный слушатель возвращает объект подписки:
const listener = map.addListener("click", handler);
Удаление:
google.maps.event.removeListener(listener);
Игнорирование удаления может приводить к накоплению обработчиков и утечкам памяти, особенно при динамическом создании и уничтожении карт.
В обработчиках событий значение this не всегда указывает
на объект карты. Поэтому предпочтительным является использование
стрелочных функций или явное сохранение ссылки:
const self = map;
map.addListener("click", function (e) {
self.setCenter(e.latLng);
});
или:
map.addListener("click", (e) => {
map.setCenter(e.latLng);
});
polyline.addListener("click", (e) => {
console.log("Клик по линии:", e.latLng);
});
polygon.addListener("click", (e) => {
console.log("Клик по полигону");
});
Дополнительно могут передаваться индексы вершин и сегментов.
События позволяют реализовывать сложную логику поверх стандартного API:
Пример динамического добавления маркера:
map.addListener("click", (e) => {
new google.maps.Marker({
position: e.latLng,
map: map
});
});
При сложных взаимодействиях важно учитывать последовательность:
mousedownmouseupclickbounds_changed (если произошло изменение)idle (после завершения всех обновлений)Понимание порядка позволяет избегать конфликтов между обработчиками.
Чрезмерное количество слушателей может приводить к снижению производительности.
Рекомендуемые практики:
addListenerOnce для одноразовых
действийmousemove и
dragСобытия API не являются DOM-событиями. Несмотря на внешнее сходство, они:
Это важно при интеграции с интерфейсом страницы, где одновременно используются DOM-события и события карты.
События можно использовать для построения цепочек реакций:
map.addListener("click", (e) => {
marker.setPosition(e.latLng);
google.maps.event.trigger(marker, "custom_move");
});
marker.addListener("custom_move", () => {
console.log("Маркер перемещён через кастомное событие");
});
Механизм trigger позволяет инициировать пользовательские
события вручную.
Один объект может иметь множество обработчиков одного события:
map.addListener("click", handler1);
map.addListener("click", handler2);
Все обработчики будут вызваны последовательно в порядке регистрации.
Исключения внутри обработчиков не всегда корректно пробрасываются наружу, поэтому логирование и защита обязательны:
map.addListener("click", (e) => {
try {
riskyOperation(e);
} catch (err) {
console.error(err);
}
});
Ключевым событием жизненного цикла карты является idle,
сигнализирующее о завершении первоначального рендеринга и загрузки
тайлов.
map.addListener("idle", () => {
console.log("Карта полностью загружена");
});
Это событие часто используется для запуска логики, зависящей от полной готовности карты.
В сложных интерфейсах слушатели добавляются и удаляются в зависимости от состояния приложения:
let clickListener = null;
function enableClick() {
clickListener = map.addListener("click", handleClick);
}
function disableClick() {
google.maps.event.removeListener(clickListener);
}
Такой подход предотвращает накопление неактуальных обработчиков и обеспечивает предсказуемое поведение интерфейса.