Google Maps JavaScript API предоставляет событийную модель,
построенную вокруг подписки на пользовательские и системные события
карты, слоёв и объектов. Архитектура событий основана на паттерне
Observer: каждый объект (карта, маркер, полигон, сервисы) генерирует
события, на которые можно подписаться через addListener,
обеспечивая реактивное поведение интерфейса.
События в API делятся на несколько категорий:
Базовый механизм подписки:
google.maps.event.addListener(instance, eventName, handler);
Также используется сокращённая форма:
instance.addListener(eventName, handler);
Отписка осуществляется через объект Listener:
const listener = map.addListener('click', () => {});
google.maps.event.removeListener(listener);
Событие click является одним из наиболее часто
используемых. Оно срабатывает при любом щелчке по поверхности карты.
map.addListener('click', (event) => {
console.log(event.latLng.lat(), event.latLng.lng());
});
Объект события содержит:
latLng — координаты точкиpixel (в некоторых контекстах) — экранные
координатыplaceId — идентификатор места (если клик по POI)Использование placeId позволяет интегрироваться с
сервисом Places:
map.addListener('click', (event) => {
if (event.placeId) {
event.stop();
}
});
Метод stop() блокирует стандартное поведение открытия
карточки места.
Карта поддерживает режим drag, генерируя последовательность событий:
dragstartdragdragendmap.addListener('dragstart', () => {
console.log('Начало перемещения карты');
});
map.addListener('dragend', () => {
console.log('Перемещение завершено');
});
drag вызывается многократно во время движения и
используется для синхронизации UI, однако требует осторожности из-за
высокой частоты вызовов.
Событие center_changed возникает при любом изменении
центра карты, включая анимации и перетаскивание.
map.addListener('center_changed', () => {
const center = map.getCenter();
});
Особенность события заключается в том, что оно может вызываться очень часто, поэтому вычислительно тяжёлые операции внутри обработчика приводят к деградации производительности.
Событие zoom_changed срабатывает при изменении уровня
увеличения карты:
map.addListener('zoom_changed', () => {
const zoom = map.getZoom();
});
Типичные сценарии:
Событие bounds_changed фиксирует любые изменения видимой
области карты.
map.addListener('bounds_changed', () => {
const bounds = map.getBounds();
});
LatLngBounds используется для:
maptypeid_changed отслеживает переключение между
слоями:
map.addListener('maptypeid_changed', () => {
const type = map.getMapTypeId();
});
Используется для адаптации визуальных слоёв и отключения/включения overlay-объектов.
Карты поддерживают низкоуровневые события мыши:
mousemovemousedownmouseuprightclickdblclickПример обработки правого клика:
map.addListener('rightclick', (event) => {
console.log('Контекстное меню координаты:', event.latLng.toString());
});
Событие dblclick часто используется для зума:
map.addListener('dblclick', (event) => {
map.setZoom(map.getZoom() + 1);
});
Маркер генерирует собственный набор событий:
clickdragstartdragdragendmouseovermouseoutconst marker = new google.maps.Marker({
position: { lat: 40, lng: -70 },
map
});
marker.addListener('click', () => {
console.log('Маркер активирован');
});
Перетаскиваемые маркеры:
const marker = new google.maps.Marker({
position: { lat: 40, lng: -70 },
map,
draggable: true
});
События drag позволяют реализовать редакторы геометрии, пользовательские точки интереса и интерактивные маршруты.
Информационные окна (InfoWindow) поддерживают:
closeclickdomreadyconst info = new google.maps.InfoWindow({
content: '<div>Точка</div>'
});
info.addListener('domready', () => {
console.log('DOM окна готов');
});
domready используется для:
Геометрические объекты (Polygon, Polyline, Circle) поддерживают:
clickmousemoverightclickpolygon.addListener('click', (event) => {
console.log(event.latLng);
});
Дополнительно доступны события редактирования:
set_atinsert_atremove_atпри использовании MVCArray в editable-режиме:
polygon.getPath().addListener('set_at', () => {
console.log('Точка изменена');
});
Некоторые события отражают внутреннее состояние рендеринга:
idle — карта завершила все изменения и загрузку
тайловtilesloaded — завершена загрузка тайловmap.addListener('idle', () => {
console.log('Карта стабилизирована');
});
idle часто используется как точка синхронизации для:
OverlayView и кастомные слои поддерживают низкоуровневые события:
class CustomOverlay extends google.maps.OverlayView {
onAdd() {}
draw() {}
onRemove() {}
}
События здесь часто реализуются вручную через внешние слушатели карты.
При большом количестве объектов важна оптимизация:
mousemoveidle вместо
bounds_changedПаттерн агрегирования событий:
let timeout;
map.addListener('bounds_changed', () => {
clearTimeout(timeout);
timeout = setTimeout(() => {
const bounds = map.getBounds();
}, 200);
});
События карты часто связаны с сервисами:
Пример интеграции с изменением границ:
map.addListener('idle', () => {
const bounds = map.getBounds();
service.nearbySearch({ bounds }, (results) => {
console.log(results);
});
});
Такой подход создаёт реактивную карту, синхронизированную с пользовательским взаимодействием.
Хотя API абстрагирует DOM, часть событий проходит через HTML-слой:
Контроль событий внутри кастомных элементов:
const controlDiv = document.createElement('div');
controlDiv.addEventListener('click', () => {
map.setZoom(map.getZoom() + 1);
});
События могут:
stop()Пример подавления:
map.addListener('click', (event) => {
if (event.placeId) {
event.stop();
}
});
Событийная модель используется как основа реактивной архитектуры:
Каждое изменение состояния карты транслируется через события, формируя непрерывный поток пользовательского взаимодействия.