Информационные окна в Google Maps JavaScript API представляют собой встроенный механизм отображения всплывающего контента, привязанного к географическим объектам карты. Базовая реализация ориентирована на простоту, однако при работе с интерфейсами повышенной сложности возникает необходимость глубокой стилизации, управления DOM-структурой и обхода ограничений стандартного компонента.
Информационное окно создаётся через конструктор
google.maps.InfoWindow. Основные параметры задаются через
объект конфигурации:
content — HTML или строка, формирующая содержимое
окнаariaLabel — доступное имя для скринридеровpixelOffset — смещение относительно маркераmaxWidth — ограничение шириныСтандартная инициализация:
const infoWindow = new google.maps.InfoWindow({
content: '<div class="info-content">Контент окна</div>',
ariaLabel: 'Информационное окно',
maxWidth: 300
});
При открытии окна через open() создаётся внутренний
DOM-узел, который инкапсулируется в структуру, управляемую Google Maps
API. Этот контейнер имеет ограниченный доступ для прямого контроля, что
формирует ключевое ограничение стилизации.
Поле content принимает HTML-строку, что позволяет
внедрять структурированную разметку. Наиболее распространённый подход —
использование обёртки с классом:
content: `
<div class="info-window">
<div class="info-window__title">Объект</div>
<div class="info-window__body">
Описание объекта на карте
</div>
</div>
`
Стилизация осуществляется через глобальные CSS-правила:
.info-window {
font-family: Arial, sans-serif;
font-size: 14px;
line-height: 1.4;
color: #222;
}
.info-window__title {
font-weight: 600;
margin-bottom: 6px;
}
.info-window__body {
color: #555;
}
Google Maps не изолирует стили InfoWindow через Shadow DOM, поэтому CSS применяется глобально, что требует аккуратного управления специфичностью селекторов.
Внутренняя структура InfoWindow содержит служебные элементы, включая контейнеры с классами, управляемыми API. Эти элементы:
Ключевое ограничение заключается в невозможности полного контроля над обёрткой окна. Например, невозможно напрямую переопределить:
Это приводит к необходимости обходных решений при создании кастомных интерфейсов.
Частичная стилизация возможна через переопределение классов, которые использует API. Среди них:
.gm-style .gm-style-iw — основной контейнер.gm-style-iw-d — внутренний контент.gm-ui-hover-effect — кнопка закрытияПример модификации стандартного окна:
.gm-style .gm-style-iw {
background-color: #1e1e1e;
border-radius: 12px;
padding: 0;
box-shadow: 0 8px 24px rgba(0,0,0,0.3);
}
.gm-style-iw-d {
overflow: hidden !important;
}
.gm-ui-hover-effect {
filter: invert(1);
}
Подобные изменения воздействуют глобально и требуют контроля конфликтов с другими компонентами карты.
Для достижения полного контроля над внешним видом применяется
OverlayView. Этот механизм позволяет создавать полностью
кастомные DOM-элементы, не ограниченные стандартной структурой
InfoWindow.
Базовая схема:
class CustomInfoWindow extends google.maps.OverlayView {
constructor(position, content) {
super();
this.position = position;
this.content = content;
this.div = null;
}
onAdd() {
this.div = document.createElement('div');
this.div.className = 'custom-info-window';
this.div.innerHTML = this.content;
const panes = this.getPanes();
panes.floatPane.appendChild(this.div);
}
draw() {
const projection = this.getProjection();
const point = projection.fromLatLngToDivPixel(this.position);
if (point && this.div) {
this.div.style.left = point.x + 'px';
this.div.style.top = point.y + 'px';
}
}
onRemove() {
if (this.div) {
this.div.parentNode.removeChild(this.div);
this.div = null;
}
}
}
Стилизация такого окна полностью контролируется разработчиком:
.custom-info-window {
position: absolute;
transform: translate(-50%, -100%);
background: #ffffff;
border-radius: 10px;
padding: 12px 16px;
box-shadow: 0 10px 30px rgba(0,0,0,0.2);
width: 240px;
}
Данный подход снимает ограничения стандартного InfoWindow и позволяет реализовывать произвольные интерфейсы.
Информационные окна часто используются для отображения данных,
изменяющихся во времени. Обновление содержимого возможно через метод
setContent:
infoWindow.setContent(`
<div class="info-window">
<div class="info-window__title">Новый заголовок</div>
<div class="info-window__body">Обновлённые данные</div>
</div>
`);
При использовании кастомных OverlayView обновление выполняется через прямое изменение DOM:
this.div.querySelector('.title').textContent = 'Обновление';
Важно учитывать, что частые обновления могут вызывать перерасчёт позиции и влиять на производительность при большом количестве объектов на карте.
Стандартный InfoWindow не предоставляет API для управления анимациями. Поэтому эффекты появления и исчезновения реализуются через CSS:
.info-window {
opacity: 0;
transform: translateY(-10px);
transition: opacity 0.2s ease, transform 0.2s ease;
}
.info-window--visible {
opacity: 1;
transform: translateY(0);
}
В JavaScript добавление класса управляет состоянием:
const el = document.querySelector('.info-window');
el.classList.add('info-window--visible');
При использовании OverlayView анимации могут применяться к контейнеру без ограничений API.
Кнопка закрытия InfoWindow является частью внутреннего DOM API и
имеет класс .gm-ui-hover-effect. Её внешний вид часто
модифицируется через фильтры и размеры:
.gm-ui-hover-effect {
width: 32px !important;
height: 32px !important;
opacity: 0.7;
}
.gm-ui-hover-effect:hover {
opacity: 1;
}
Изменение поведения кнопки напрямую невозможно, однако возможно управление через перехват событий на уровне контейнера карты.
Информационные окна должны учитывать различные разрешения экрана и плотность пикселей. Типичные техники адаптации:
.info-window {
max-width: 90vw;
font-size: clamp(12px, 2vw, 14px);
}
Для мобильных устройств применяется ограничение высоты:
.info-window__body {
max-height: 40vh;
overflow-y: auto;
}
При работе с мобильными картами важно учитывать смещение окна относительно маркера, так как ограниченное пространство экрана влияет на видимость содержимого.
InfoWindow допускает использование сложных HTML-структур, включая списки, изображения и интерактивные элементы:
content: `
<div class="info-window">
<div class="info-window__title">Объект инфраструктуры</div>
<img src="image.jpg" class="info-window__image" />
<ul class="info-window__list">
<li>Параметр 1</li>
<li>Параметр 2</li>
</ul>
</div>
`
Однако взаимодействие с такими элементами требует учёта повторного рендера окна при каждом открытии, что может приводить к потере состояния DOM-элементов.
Одновременное использование нескольких InfoWindow на одной карте требует явного управления экземплярами. Стандартный подход предполагает закрытие предыдущего окна перед открытием нового:
if (currentInfoWindow) {
currentInfoWindow.close();
}
currentInfoWindow = new google.maps.InfoWindow({
content: 'Новый контент'
});
currentInfoWindow.open(map, marker);
При использовании OverlayView управление осуществляется через массив
активных экземпляров и ручное удаление через
setMap(null).
При построении интерфейсов уровня геоинформационных систем InfoWindow часто становится частью более сложной архитектуры, включающей:
В таких случаях стандартный InfoWindow используется как базовый элемент, а основная логика визуализации переносится в кастомные оверлеи, обеспечивающие полный контроль над DOM и состоянием интерфейса.