Оверлеи (Overlay) в Google Maps JavaScript API позволяют размещать поверх карты собственные визуальные элементы, не ограничиваясь стандартными маркерами, информационными окнами и фигурами. Пользовательский оверлей может представлять собой изображение, HTML-блок, интерактивную панель, всплывающую подсказку, схему здания, слой данных или любой другой элемент интерфейса.
Для создания таких объектов используется базовый класс OverlayView, который предоставляет доступ к жизненному циклу оверлея и механизмам преобразования географических координат в экранные координаты.
Основные возможности пользовательских оверлеев:
Класс google.maps.OverlayView является абстрактным
базовым классом. Для создания собственного оверлея необходимо
унаследоваться от него и реализовать ряд методов жизненного цикла.
Стандартная структура выглядит следующим образом:
class CustomOverlay extends google.maps.OverlayView {
constructor(bounds, element) {
super();
this.bounds = bounds;
this.element = element;
}
onAdd() {
}
draw() {
}
onRemove() {
}
}
Google Maps автоматически вызывает эти методы в нужные моменты работы карты.
Вызывается после добавления оверлея на карту.
В этом методе обычно:
Пример:
onAdd() {
const div = document.createElement("div");
div.className = "custom-overlay";
div.innerHTML = `
<div class="info-panel">
Москва
</div>
`;
this.div = div;
const panes = this.getPanes();
panes.overlayLayer.appendChild(div);
}
Вызывается:
Именно здесь происходит вычисление положения элемента на экране.
draw() {
}
Вызывается при удалении оверлея с карты.
Здесь необходимо освобождать ресурсы и удалять DOM-элементы.
onRemove() {
if (this.div) {
this.div.remove();
this.div = null;
}
}
Google Maps содержит несколько слоев отображения.
Получить их можно через:
const panes = this.getPanes();
Доступны следующие панели:
| Панель | Назначение |
|---|---|
| mapPane | Базовый слой карты |
| overlayLayer | Большинство пользовательских элементов |
| markerLayer | Маркеры |
| overlayMouseTarget | Элементы, обрабатывающие события мыши |
| floatPane | Информационные окна |
Пример:
panes.overlayMouseTarget.appendChild(div);
Такой элемент сможет получать события мыши.
Для вычисления положения элементов используется объект проекции:
const projection = this.getProjection();
Он позволяет переводить координаты карты в пиксельные координаты.
Основной метод:
projection.fromLatLngToDivPixel()
Пример:
const position = projection.fromLatLngToDivPixel(
new google.maps.LatLng(55.7558, 37.6176)
);
Результат:
{
x: 412,
y: 286
}
Полученные координаты используются для позиционирования HTML-элементов.
Создадим окно с текстом поверх карты.
class LabelOverlay extends google.maps.OverlayView {
constructor(position, text) {
super();
this.position = position;
this.text = text;
}
onAdd() {
this.div = document.createElement("div");
this.div.className = "label-overlay";
this.div.textContent = this.text;
this.getPanes()
.overlayMouseTarget
.appendChild(this.div);
}
draw() {
const projection = this.getProjection();
const pixel =
projection.fromLatLngToDivPixel(
this.position
);
this.div.style.left = pixel.x + "px";
this.div.style.top = pixel.y + "px";
}
onRemove() {
this.div.remove();
}
}
const overlay = new LabelOverlay(
new google.maps.LatLng(
55.7558,
37.6176
),
"Центр Москвы"
);
overlay.setMap(map);
Метод:
setMap(map);
добавляет оверлей на карту.
Большинство пользовательских оверлеев используют CSS-позиционирование.
.label-overlay {
position: absolute;
background: white;
padding: 8px 12px;
border-radius: 6px;
box-shadow: 0 2px 8px rgba(0,0,0,.2);
}
Поскольку элемент располагается поверх карты, используется:
position: absolute;
По умолчанию верхний левый угол элемента будет совпадать с координатой точки.
Для центрирования используется CSS-трансформация:
.label-overlay {
position: absolute;
transform: translate(-50%, -100%);
}
Результат:
Часто требуется наложить изображение на определенную область карты.
Например:
class ImageOverlay extends google.maps.OverlayView {
constructor(bounds, image) {
super();
this.bounds = bounds;
this.image = image;
}
}
onAdd() {
const div = document.createElement("div");
const img = document.createElement("img");
img.src = this.image;
img.style.width = "100%";
img.style.height = "100%";
div.appendChild(img);
this.div = div;
this.getPanes()
.overlayLayer
.appendChild(div);
}
В методе draw() необходимо вычислять размеры и положение
изображения.
draw() {
const projection =
this.getProjection();
const sw =
projection.fromLatLngToDivPixel(
this.bounds.getSouthWest()
);
const ne =
projection.fromLatLngToDivPixel(
this.bounds.getNorthEast()
);
const div = this.div;
div.style.left = sw.x + "px";
div.style.top = ne.y + "px";
div.style.width =
(ne.x - sw.x) + "px";
div.style.height =
(sw.y - ne.y) + "px";
}
Теперь изображение автоматически изменяет размер при масштабировании карты.
Поскольку оверлей представляет собой обычный HTML, внутри него могут находиться любые элементы интерфейса.
Пример:
this.div.innerHTML = `
<div class="popup">
<h3>Склад</h3>
<button id="details">
Подробнее
</button>
</div>
`;
Можно подключать обработчики событий:
this.div
.querySelector("#details")
.addEventListener("click", () => {
console.log("Открытие карточки");
});
Для интерактивных оверлеев рекомендуется использовать слой:
overlayMouseTarget
Пример:
this.getPanes()
.overlayMouseTarget
.appendChild(this.div);
Теперь будут работать:
click
dblclick
mouseover
mouseout
mousemove
Иногда при работе с элементами интерфейса необходимо блокировать передачу событий карте.
Google Maps предоставляет специальные методы:
google.maps.OverlayView.preventMapHitsFrom(
element
);
Пример:
google.maps.OverlayView
.preventMapHitsFrom(
this.div
);
Теперь щелчки не будут достигать карты.
Для полной блокировки жестов:
google.maps.OverlayView
.preventMapHitsAndGesturesFrom(
this.div
);
Будут отключены:
Оверлей можно скрывать без удаления.
this.div.style.display = "none";
Показ:
this.div.style.display = "block";
Методы класса:
hide() {
this.div.style.display = "none";
}
show() {
this.div.style.display = "block";
}
Для полного удаления используется:
overlay.setMap(null);
После вызова:
overlay.setMap(null);
Google Maps автоматически выполнит:
onRemove()
и очистит элемент.
Поскольку оверлей является HTML-элементом, доступны любые CSS-анимации.
Пример появления:
.overlay {
opacity: 0;
animation: fadeIn .3s forwards;
}
@keyframes fadeIn {
from {
opacity: 0;
}
to {
opacity: 1;
}
}
Распространенный сценарий — отображение карточек объектов непосредственно на карте.
Структура:
<div class="property-card">
<img src="house.jpg">
<h3>Дом</h3>
<p>120 м²</p>
</div>
Такой элемент может отображаться:
При создании сотен элементов необходимо учитывать нагрузку на DOM.
Основные рекомендации:
Минимизировать количество HTML-узлов
Плохо:
<div>
<div>
<div>
<span>
</span>
</div>
</div>
</div>
Лучше:
<div class="marker-label">
Точка
</div>
Избегать тяжелых вычислений внутри draw()
Метод вызывается очень часто.
Плохо:
draw() {
expensiveCalculation();
}
Лучше:
draw() {
updatePosition();
}
Удалять неиспользуемые обработчики
Перед удалением элемента:
button.removeEventListener(
"click",
handler
);
Не создавать DOM заново
Плохо:
draw() {
this.div =
document.createElement("div");
}
Правильно:
onAdd() {
this.div =
document.createElement("div");
}
class CustomOverlay extends google.maps.OverlayView {
constructor(position, html) {
super();
this.position = position;
this.html = html;
}
onAdd() {
this.div = document.createElement("div");
this.div.className = "custom-overlay";
this.div.innerHTML = this.html;
this.getPanes()
.overlayMouseTarget
.appendChild(this.div);
google.maps.OverlayView
.preventMapHitsFrom(
this.div
);
}
draw() {
const projection =
this.getProjection();
const pixel =
projection.fromLatLngToDivPixel(
this.position
);
this.div.style.left =
pixel.x + "px";
this.div.style.top =
pixel.y + "px";
this.div.style.transform =
"translate(-50%, -100%)";
}
onRemove() {
if (this.div) {
this.div.remove();
this.div = null;
}
}
}
Использование:
const overlay =
new CustomOverlay(
{
lat: 55.7558,
lng: 37.6176
},
`
<div class="popup">
<h3>Москва</h3>
<p>Пользовательский оверлей</p>
</div>
`
);
overlay.setMap(map);
Подобная архитектура служит основой для построения сложных интерфейсов поверх карты: информационных панелей, интерактивных меток, визуализации объектов недвижимости, навигационных подсказок, схем помещений, картографических редакторов и специализированных геоинформационных систем.