Обработка событий маркеров

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

В Google Maps JavaScript API события маркеров реализованы через механизм прослушивателей событий (event listeners), который обеспечивает выполнение пользовательского кода при наступлении определённых действий.

Базовый принцип работы выглядит следующим образом:

marker.addListener("click", () => {
    console.log("Маркер нажат");
});

После регистрации обработчика функция будет вызываться каждый раз при возникновении указанного события.


Добавление обработчиков событий

Для регистрации обработчика используется метод addListener().

Пример создания маркера:

const marker = new google.maps.Marker({
    position: {
        lat: 55.7558,
        lng: 37.6176
    },
    map: map,
    title: "Москва"
});

Добавление обработчика:

marker.addListener("click", () => {
    alert("Выбран маркер Москвы");
});

Событие связывается исключительно с данным экземпляром маркера.


Событие click

Событие click является наиболее распространённым событием маркеров.

Оно возникает при нажатии левой кнопкой мыши на объект.

marker.addListener("click", () => {
    console.log("Клик по маркеру");
});

Типичные сценарии применения:

  • открытие информационного окна;
  • переход к карточке объекта;
  • загрузка данных с сервера;
  • выделение выбранного объекта;
  • запуск анимации.

Пример открытия информационного окна:

const infoWindow = new google.maps.InfoWindow({
    content: "<h3>Москва</h3>"
});

marker.addListener("click", () => {
    infoWindow.open({
        anchor: marker,
        map
    });
});

Событие dblclick

Событие dblclick вызывается при двойном щелчке по маркеру.

marker.addListener("dblclick", () => {
    console.log("Двойной клик");
});

Применяется для:

  • быстрого масштабирования;
  • перехода в режим редактирования;
  • открытия расширенной информации.

Пример:

marker.addListener("dblclick", () => {
    map.setZoom(15);
    map.panTo(marker.getPosition());
});

Событие rightclick

Для обработки нажатия правой кнопкой мыши используется событие rightclick.

marker.addListener("rightclick", () => {
    console.log("Контекстное меню");
});

Часто применяется для:

  • удаления объектов;
  • отображения контекстных меню;
  • административных функций.

Пример:

marker.addListener("rightclick", () => {
    marker.setMap(null);
});

После выполнения обработчика маркер будет удалён с карты.


Событие mousedown

Событие возникает в момент нажатия кнопки мыши.

marker.addListener("mousedown", () => {
    console.log("Кнопка нажата");
});

Используется для:

  • начала перетаскивания;
  • выделения объекта;
  • запуска пользовательских жестов.

Событие mouseup

Вызывается после отпускания кнопки мыши.

marker.addListener("mouseup", () => {
    console.log("Кнопка отпущена");
});

Обычно работает совместно с mousedown.


Событие mouseover

Событие возникает при наведении указателя мыши на маркер.

marker.addListener("mouseover", () => {
    console.log("Наведение");
});

Распространённые сценарии:

  • показ всплывающих подсказок;
  • подсветка объекта;
  • изменение внешнего вида маркера.

Пример увеличения иконки:

marker.addListener("mouseover", () => {
    marker.setIcon({
        url: "icon-large.png",
        scaledSize: new google.maps.Size(50, 50)
    });
});

Событие mouseout

Срабатывает при уходе курсора с маркера.

marker.addListener("mouseout", () => {
    console.log("Курсор покинул маркер");
});

Обычно используется для отмены изменений, выполненных в mouseover.

marker.addListener("mouseout", () => {
    marker.setIcon({
        url: "icon.png",
        scaledSize: new google.maps.Size(32, 32)
    });
});

Событие dragstart

Если маркер является перетаскиваемым, можно отслеживать начало перемещения.

Создание перетаскиваемого маркера:

const marker = new google.maps.Marker({
    position: position,
    map: map,
    draggable: true
});

Обработка начала перемещения:

marker.addListener("dragstart", () => {
    console.log("Начало перетаскивания");
});

Полезно для:

  • блокировки интерфейса;
  • сохранения исходных координат;
  • подготовки к обновлению данных.

Событие drag

Во время перемещения маркера постоянно генерируется событие drag.

marker.addListener("drag", () => {
    console.log("Маркер перемещается");
});

Получение текущих координат:

marker.addListener("drag", () => {
    const pos = marker.getPosition();

    console.log(
        pos.lat(),
        pos.lng()
    );
});

Событие может вызываться десятки раз в секунду, поэтому тяжёлые вычисления внутри обработчика нежелательны.


Событие dragend

Вызывается после завершения перемещения.

marker.addListener("dragend", () => {
    console.log("Перетаскивание завершено");
});

Получение новых координат:

marker.addListener("dragend", () => {
    const position = marker.getPosition();

    console.log(position.lat());
    console.log(position.lng());
});

Часто используется для сохранения координат на сервере.

marker.addListener("dragend", async () => {
    const position = marker.getPosition();

    await fetch("/save-location", {
        method: "POST",
        body: JSON.stringify({
            lat: position.lat(),
            lng: position.lng()
        })
    });
});

Получение объекта события

Некоторые обработчики получают объект события в качестве параметра.

marker.addListener("click", (event) => {
    console.log(event);
});

Объект содержит полезную информацию о произошедшем действии.

Пример:

marker.addListener("click", (event) => {
    console.log(event.latLng.lat());
    console.log(event.latLng.lng());
});

Координаты позволяют определить точку взаимодействия пользователя.


Использование именованных функций

Вместо анонимных функций допускается применение отдельных обработчиков.

function handleMarkerClick() {
    console.log("Маркер выбран");
}

marker.addListener("click", handleMarkerClick);

Преимущества подхода:

  • улучшение читаемости;
  • повторное использование логики;
  • упрощение тестирования;
  • удобство удаления обработчиков.

Удаление обработчиков событий

Метод addListener() возвращает объект прослушивателя.

const listener = marker.addListener("click", () => {
    console.log("Клик");
});

Удаление:

listener.remove();

Альтернативный вариант:

google.maps.event.removeListener(listener);

После удаления функция больше не будет вызываться.


Очистка всех обработчиков

Иногда требуется полностью очистить объект от событий.

google.maps.event.clearInstanceListeners(marker);

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


Несколько обработчиков одного события

Для одного события может существовать несколько независимых слушателей.

marker.addListener("click", () => {
    console.log("Первый обработчик");
});

marker.addListener("click", () => {
    console.log("Второй обработчик");
});

marker.addListener("click", () => {
    console.log("Третий обработчик");
});

Все функции будут выполнены последовательно.


Изменение состояния маркера при событиях

События часто используются для изменения визуального состояния объекта.

Пример переключения анимации:

marker.addListener("click", () => {
    marker.setAnimation(
        google.maps.Animation.BOUNCE
    );
});

Остановка анимации через некоторое время:

marker.addListener("click", () => {

    marker.setAnimation(
        google.maps.Animation.BOUNCE
    );

    setTimeout(() => {
        marker.setAnimation(null);
    }, 2000);

});

Работа с несколькими маркерами

При создании набора маркеров обработчики обычно назначаются в цикле.

locations.forEach(location => {

    const marker = new google.maps.Marker({
        position: location.position,
        map: map,
        title: location.name
    });

    marker.addListener("click", () => {
        console.log(location.name);
    });

});

Каждый обработчик получает доступ к данным конкретного объекта.


Использование замыканий для передачи данных

Замыкания позволяют связывать дополнительные данные с событием.

function createMarker(city) {

    const marker = new google.maps.Marker({
        position: city.position,
        map: map
    });

    marker.addListener("click", () => {
        alert(city.name);
    });

    return marker;
}

Каждый обработчик сохраняет ссылку на объект города даже после завершения функции.


Создание универсального обработчика

При большом количестве маркеров удобно использовать единую функцию.

function handleCityClick(city) {
    console.log(city.name);
}

locations.forEach(city => {

    const marker = new google.maps.Marker({
        position: city.position,
        map: map
    });

    marker.addListener("click", () => {
        handleCityClick(city);
    });

});

Подобная архитектура значительно упрощает поддержку приложения.


Комбинирование нескольких событий

Для одного маркера можно организовать комплексное взаимодействие.

marker.addListener("mouseover", () => {
    console.log("Наведение");
});

marker.addListener("mouseout", () => {
    console.log("Уход курсора");
});

marker.addListener("click", () => {
    console.log("Выбор объекта");
});

marker.addListener("dragend", () => {
    console.log("Новая позиция");
});

Такой подход позволяет реализовать поведение, характерное для полноценных картографических интерфейсов.


Типичные сценарии обработки событий маркеров

Открытие карточки объекта

marker.addListener("click", () => {
    openPropertyCard(propertyId);
});

Подсветка при наведении

marker.addListener("mouseover", () => {
    marker.setZIndex(1000);
});

marker.addListener("mouseout", () => {
    marker.setZIndex(null);
});

Сохранение координат после перемещения

marker.addListener("dragend", () => {

    const pos = marker.getPosition();

    saveCoordinates({
        lat: pos.lat(),
        lng: pos.lng()
    });

});

Отображение координат в форме

marker.addListener("drag", () => {

    const pos = marker.getPosition();

    latitudeInput.value = pos.lat();
    longitudeInput.value = pos.lng();

});

Масштабирование карты к объекту

marker.addListener("click", () => {

    map.panTo(marker.getPosition());

    map.setZoom(16);

});

Рекомендации по производительности

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

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

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