Обработка событий фигур

В Google Maps JavaScript API все графические объекты на карте — маркеры, линии, полигоны, окружности и прямоугольники — построены на основе событийной модели, позволяющей реагировать на действия пользователя и изменения состояния объектов в реальном времени. Обработка событий фигур опирается на единый механизм google.maps.event, а также на внутренние события самих MVC-объектов, таких как MVCArray, который используется для хранения координатных наборов.

Каждая фигура в API наследует поведение, позволяющее регистрировать слушатели событий через:

google.maps.event.addListener(instance, eventName, handler);

или более современную форму:

instance.addListener(eventName, handler);

Оба варианта функционально эквивалентны, однако второй чаще используется в современном коде из-за читаемости и привязки к конкретному объекту.

Удаление обработчиков выполняется через объект слушателя:

const listener = google.maps.event.addListener(polygon, 'click', () => {
  console.log('click');
});

google.maps.event.removeListener(listener);

События фигур не блокируют основное выполнение скрипта, но могут влиять на состояние карты и связанные элементы интерфейса, такие как информационные окна или панели редактирования.

События маркеров как основа взаимодействия

Хотя маркеры не являются сложными геометрическими фигурами, они формируют основу событийной модели:

marker.addListener('click', (event) => {
  console.log(event.latLng.toString());
});

Событие click передает объект MouseEvent, содержащий координаты latLng, пиксельные координаты и ссылку на DOM-событие.

Маркер поддерживает также:

  • dragstart
  • drag
  • dragend
  • mouseover
  • mouseout

При включенной опции draggable: true события перетаскивания становятся ключевыми для обновления состояния приложения.

Полилинии и реакция на изменение пути

Полилинии используют структуру MVCArray для хранения координат. Это означает, что изменение геометрии можно отслеживать на уровне массива:

polyline.getPath().addListener('insert_at', (index) => {
  console.log('Добавлена точка:', index);
});

polyline.getPath().addListener('set_at', (index) => {
  console.log('Изменена точка:', index);
});

polyline.getPath().addListener('remove_at', (index) => {
  console.log('Удалена точка:', index);
});

Эти события не относятся к google.maps.event, а являются частью реактивной модели MVCArray, что делает их особенно важными при реализации редакторов маршрутов.

Дополнительно сама полилиния поддерживает события:

  • click
  • mousemove
  • rightclick

При этом событие mousemove может генерироваться с высокой частотой, что требует оптимизации обработчиков.

Полигоны и сложные области

Полигон расширяет модель полилинии, добавляя замкнутую область и возможность работы с внутренними отверстиями (holes). Основные события аналогичны:

polygon.addListener('click', (event) => {
  console.log(event.latLng);
});

Особое значение имеет доступ к изменению вершин:

polygon.getPath().addListener('set_at', () => {
  console.log('Изменение внешнего контура');
});

Если полигон содержит несколько контуров, каждый из них представлен отдельным MVCArray, и обработка событий должна учитывать индекс пути:

polygon.getPaths().forEach((path, index) => {
  path.addListener('insert_at', () => {
    console.log('Изменение в контуре', index);
  });
});

Окружности и события изменения параметров

Окружность состоит из двух ключевых параметров: центра и радиуса. События привязаны к маркероподобной модели изменения:

circle.addListener('center_changed', () => {
  console.log(circle.getCenter());
});

circle.addListener('radius_changed', () => {
  console.log(circle.getRadius());
});

В отличие от полигонов, окружность не использует MVCArray, но предоставляет прямые события для ключевых свойств.

Прямоугольники и изменение границ

Прямоугольник работает через объект LatLngBounds, что определяет северо-восточную и юго-западную границы.

rectangle.addListener('bounds_changed', () => {
  console.log(rectangle.getBounds());
});

Изменение границ может происходить как через API, так и через интерактивное редактирование, если включен режим editable.

Работа с событиями мыши и координатами

Практически все фигуры поддерживают стандартные события указателя:

  • click
  • dblclick
  • mousedown
  • mouseup
  • mouseover
  • mouseout
  • mousemove
  • rightclick

Каждое событие содержит объект:

{
  latLng: LatLng,
  domEvent: MouseEvent
}

latLng является основным источником географических координат, используемых для дальнейших вычислений или построения новых объектов.

Привязка контекста и проблема this

В обработчиках событий значение this не всегда указывает на ожидаемый объект. В большинстве случаев рекомендуется явно использовать замыкания:

polygon.addListener('click', function (event) {
  console.log(this.getPath());
});

Однако в строгих режимах или при использовании стрелочных функций this теряет привязку:

polygon.addListener('click', (event) => {
  console.log(this); // не polygon
});

Поэтому для доступа к фигуре предпочтительнее использовать внешнюю переменную:

const poly = polygon;

poly.addListener('click', (event) => {
  console.log(poly.getPath());
});

Редактируемые фигуры и динамическая обработка

При включении editable: true фигуры начинают генерировать дополнительные события изменения геометрии. Это особенно важно для интерактивных картографических редакторов.

Для полигона:

const polygon = new google.maps.Polygon({
  editable: true,
  draggable: true
});

Изменение вершин автоматически вызывает события set_at, insert_at, remove_at, а также может приводить к цепочке click и mousemove событий.

События при перетаскивании фигур

Для объектов с включенным draggable доступны события:

  • dragstart
  • drag
  • dragend
polygon.addListener('dragend', (event) => {
  console.log('Новая позиция фигуры');
});

Для окружностей и прямоугольников перетаскивание влияет на центр или границы соответственно, что приводит к пересчету геометрии в реальном времени.

Сложные сценарии взаимодействия

При построении интерактивных редакторов карт часто комбинируются несколько уровней событий:

  • события кликов для добавления вершин
  • события MVCArray для отслеживания структуры
  • события перетаскивания для изменения положения
  • события изменения свойств для синхронизации состояния

Пример комбинированной логики:

polygon.addListener('click', (e) => {
  const path = polygon.getPath();
  path.push(e.latLng);
});

polygon.getPath().addListener('set_at', () => {
  updateServerState(polygon.getPath().getArray());
});

Производительность обработки событий

События mousemove и drag могут генерироваться десятки раз в секунду. Это требует ограничения частоты обработки:

let lastUpdate = 0;

polygon.addListener('mousemove', (e) => {
  const now = Date.now();
  if (now - lastUpdate < 50) return;

  lastUpdate = now;
  console.log(e.latLng);
});

Такая схема предотвращает перегрузку интерфейса и снижает нагрузку на основной поток.

Взаимодействие событий фигур с другими слоями карты

События фигур могут конфликтовать с событиями карты. Например, клик по полигону может одновременно вызывать click карты. Управление этим поведением осуществляется через:

google.maps.event.addListener(polygon, 'click', (e) => {
  google.maps.event.trigger(map, 'customClick', e);
});

Таким образом создается цепочка пользовательских событий, позволяющая строить сложные сценарии взаимодействия между слоями карты и графическими объектами.