InfoWindow основы

InfoWindow — встроенный компонент Google Maps JavaScript API, предназначенный для отображения информационных окон поверх карты. Обычно используется для вывода сведений о маркерах, объектах инфраструктуры, координатах, результатах поиска и пользовательских данных.

Информационное окно представляет собой всплывающий контейнер, который может содержать:

  • обычный текст;
  • HTML-разметку;
  • изображения;
  • ссылки;
  • таблицы;
  • динамически сформированный контент.

Окно автоматически позиционируется относительно заданной точки на карте или привязанного маркера.


Создание InfoWindow

Для создания информационного окна используется класс google.maps.InfoWindow.

Простейший пример:

const infoWindow = new google.maps.InfoWindow({
    content: "Информация о точке"
});

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


Свойство content

Основным параметром является content.

Текстовое содержимое

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

Результатом станет простое окно с текстом.


HTML-содержимое

Внутри окна может размещаться полноценная HTML-разметка.

const infoWindow = new google.maps.InfoWindow({
    content: `
        <div>
            <h3>Москва</h3>
            <p>Столица Российской Федерации.</p>
        </div>
    `
});

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


Использование DOM-элемента

В качестве содержимого можно передавать HTML-элемент.

const container = document.createElement("div");

container.innerHTML = `
    <h3>Точка интереса</h3>
    <p>Описание объекта</p>
`;

const infoWindow = new google.maps.InfoWindow({
    content: container
});

Подход удобен при генерации интерфейса средствами JavaScript.


Отображение окна

Для показа окна применяется метод open().

Пример:

infoWindow.open({
    map: map
});

После выполнения окно появляется на карте.


Открытие в конкретной позиции

InfoWindow может отображаться в произвольных координатах.

const infoWindow = new google.maps.InfoWindow({
    content: "Точка на карте",
    position: {
        lat: 55.7558,
        lng: 37.6176
    }
});

infoWindow.open({
    map: map
});

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


Привязка к маркеру

Наиболее распространённый сценарий — показ окна при взаимодействии с маркером.

const marker = new google.maps.Marker({
    position: {
        lat: 55.7558,
        lng: 37.6176
    },
    map: map
});

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

infoWindow.open({
    anchor: marker,
    map: map
});

Окно будет автоматически располагаться над маркером.


Открытие по клику на маркер

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

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

Такой механизм обеспечивает привычное поведение интерактивной карты.


Динамическое изменение содержимого

Контент можно менять после создания окна.

infoWindow.setContent("Новое содержимое");

Либо использовать HTML.

infoWindow.setContent(`
    <div>
        <strong>Обновлённая информация</strong>
    </div>
`);

Это позволяет переиспользовать одно окно для множества объектов.


Изменение позиции

Для перемещения окна применяется метод setPosition().

infoWindow.setPosition({
    lat: 59.9386,
    lng: 30.3141
});

После изменения координат окно можно открыть повторно.


Закрытие окна

Для скрытия используется метод close().

infoWindow.close();

После вызова окно исчезает с карты, но объект продолжает существовать.


Повторное открытие

Закрытое окно можно показывать неограниченное количество раз.

infoWindow.close();

infoWindow.open({
    anchor: marker,
    map: map
});

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


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

Создание отдельного InfoWindow для каждого маркера может приводить к лишним затратам памяти. Часто применяется один экземпляр окна, который обновляет содержимое при выборе объекта.

const infoWindow = new google.maps.InfoWindow();

markers.forEach(marker => {

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

        infoWindow.setContent(marker.title);

        infoWindow.open({
            anchor: marker,
            map: map
        });

    });

});

Такой подход считается оптимальным для карт с большим количеством объектов.


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

Часто информация хранится внутри массива объектов.

const places = [
    {
        name: "Москва",
        description: "Столица России",
        lat: 55.7558,
        lng: 37.6176
    },
    {
        name: "Санкт-Петербург",
        description: "Культурная столица",
        lat: 59.9386,
        lng: 30.3141
    }
];

Создание маркеров:

places.forEach(place => {

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

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

        infoWindow.setContent(`
            <div>
                <h3>${place.name}</h3>
                <p>${place.description}</p>
            </div>
        `);

        infoWindow.open({
            anchor: marker,
            map: map
        });

    });

});

Свойство ariaLabel

Для повышения доступности интерфейса используется параметр ariaLabel.

const infoWindow = new google.maps.InfoWindow({
    content: "Описание объекта",
    ariaLabel: "Информация о достопримечательности"
});

Данное описание применяется вспомогательными технологиями и экранными дикторами.


Максимальная ширина окна

Размер окна можно ограничить через maxWidth.

const infoWindow = new google.maps.InfoWindow({
    content: longContent,
    maxWidth: 300
});

Если контент превышает указанную ширину, браузер выполнит перенос строк.


Минимальная ширина окна

Для сохранения структуры интерфейса можно использовать minWidth.

const infoWindow = new google.maps.InfoWindow({
    content: content,
    minWidth: 250
});

Особенно полезно при отображении карточек с одинаковым дизайном.


Работа с событиями

InfoWindow поддерживает собственную систему событий.

closeclick

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

infoWindow.addListener("closeclick", () => {
    console.log("Окно закрыто");
});

content_changed

Вызывается после изменения содержимого.

infoWindow.addListener("content_changed", () => {
    console.log("Контент обновлён");
});

position_changed

Срабатывает после изменения позиции.

infoWindow.addListener("position_changed", () => {
    console.log("Позиция изменена");
});

visible

Позволяет определить момент отображения окна.

infoWindow.addListener("visible", () => {
    console.log("Окно показано");
});

Формирование карточек объектов

InfoWindow часто используется для создания мини-карточек.

Пример:

const html = `
<div class="card">
    <img
        src="images/hotel.jpg"
        alt="Отель"
        width="250"
    >

    <h3>Отель Premium</h3>

    <p>
        Расстояние до центра: 1.2 км
    </p>

    <a href="/hotel/1">
        Подробнее
    </a>
</div>
`;

const infoWindow = new google.maps.InfoWindow({
    content: html
});

Такой формат широко применяется в сервисах бронирования, навигационных системах и геоинформационных приложениях.


Автоматическое закрытие предыдущего окна

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

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

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

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

Лучше использовать единый экземпляр:

const infoWindow = new google.maps.InfoWindow();

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

    infoWindow.close();

    infoWindow.setContent(data);

    infoWindow.open({
        anchor: marker,
        map: map
    });

});

В результате на карте одновременно отображается только одно окно.


Безопасность при вставке HTML

При формировании содержимого из пользовательских данных необходимо учитывать риск XSS-атак.

Небезопасный вариант:

infoWindow.setContent(`
    <div>${userInput}</div>
`);

Если строка содержит вредоносный HTML или JavaScript, это может привести к компрометации приложения.

Безопаснее использовать предварительную фильтрацию данных либо создавать DOM-элементы программно.

const div = document.createElement("div");

div.textContent = userInput;

infoWindow.setContent(div);

Типичный сценарий использования

Полный пример карты с маркером и информационным окном:

const map = new google.maps.Map(
    document.getElementById("map"),
    {
        center: {
            lat: 55.7558,
            lng: 37.6176
        },
        zoom: 10
    }
);

const marker = new google.maps.Marker({
    position: {
        lat: 55.7558,
        lng: 37.6176
    },
    map: map
});

const infoWindow = new google.maps.InfoWindow({
    content: `
        <div>
            <h3>Москва</h3>
            <p>Крупнейший город России.</p>
        </div>
    `
});

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

    infoWindow.open({
        anchor: marker,
        map: map
    });

});

В данном примере реализованы основные возможности InfoWindow: создание окна, размещение HTML-контента, привязка к маркеру и отображение по пользовательскому событию.