Стандартные объекты Google Maps JavaScript API, такие как маркеры, информационные окна, полигоны и полилинии, покрывают большинство типовых задач. Однако при разработке сложных картографических интерфейсов часто возникает необходимость отображать собственные HTML-элементы, изображения, интерактивные панели, диаграммы, визуализации данных или полностью кастомные графические объекты поверх карты.
Для таких задач используется механизм Custom
Overlays, основанный на классе OverlayView.
OverlayView предоставляет доступ к внутренним механизмам
отрисовки карты и позволяет:
Custom Overlay является мостом между географическими координатами и DOM-элементами браузера.
Все пользовательские оверлеи наследуются от класса:
google.maps.OverlayView
При создании собственного класса необходимо реализовать специальные методы жизненного цикла:
class CustomOverlay extends google.maps.OverlayView {
onAdd() {}
draw() {}
onRemove() {}
}
Каждый из этих методов выполняет определённую задачу.
| Метод | Назначение |
|---|---|
| onAdd() | Добавление DOM-элементов на карту |
| draw() | Позиционирование и обновление |
| onRemove() | Очистка ресурсов |
Минимальная структура выглядит следующим образом:
class CustomOverlay extends google.maps.OverlayView {
constructor(bounds, image) {
super();
this.bounds = bounds;
this.image = image;
this.div = null;
}
onAdd() {
}
draw() {
}
onRemove() {
}
}
В конструкторе обычно сохраняются:
Метод вызывается автоматически после добавления оверлея на карту.
Именно здесь создаются HTML-элементы.
Пример:
onAdd() {
const div = document.createElement("div");
div.style.position = "absolute";
const img = document.createElement("img");
img.src = this.image;
img.style.width = "100%";
img.style.height = "100%";
div.appendChild(img);
this.div = div;
const panes = this.getPanes();
panes.overlayLayer.appendChild(div);
}
Ключевым моментом является использование метода:
this.getPanes()
Он предоставляет доступ к слоям карты.
Google Maps содержит несколько слоёв отображения.
Получить их можно так:
const panes = this.getPanes();
Доступны следующие панели:
| Панель | Назначение |
|---|---|
| mapPane | Базовый слой карты |
| overlayLayer | Оверлеи без событий |
| markerLayer | Слой маркеров |
| overlayMouseTarget | Оверлеи с поддержкой событий мыши |
| floatPane | Информационные окна |
Пример размещения интерактивного элемента:
panes.overlayMouseTarget.appendChild(div);
Такой элемент сможет получать клики.
Метод отвечает за вычисление позиции оверлея на экране.
Вызывается при:
Для преобразования географических координат используются проекции карты.
Получение объекта проекции:
const projection = this.getProjection();
Преобразование координат:
projection.fromLatLngToDivPixel()
Пусть имеется точка:
const position = new google.maps.LatLng(
55.751244,
37.618423
);
Получение экранных координат:
const pixel = projection.fromLatLngToDivPixel(position);
Результат:
{
x: 428,
y: 315
}
После этого можно позиционировать элемент:
this.div.style.left = `${pixel.x}px`;
this.div.style.top = `${pixel.y}px`;
Часто Overlay используется для размещения изображений поверх определённого участка карты.
Например:
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`;
}
Так изображение автоматически масштабируется вместе с картой.
Вызывается при удалении оверлея.
Здесь освобождаются ресурсы и удаляются DOM-элементы.
Пример:
onRemove() {
if (this.div) {
this.div.parentNode.removeChild(this.div);
this.div = null;
}
}
Игнорирование очистки может приводить к утечкам памяти.
После создания экземпляра необходимо связать его с картой.
const overlay = new CustomOverlay(
bounds,
imageUrl
);
overlay.setMap(map);
Метод:
setMap()
запускает жизненный цикл объекта.
Последовательность вызовов:
setMap()
↓
onAdd()
↓
draw()
Удаление выполняется через тот же метод.
overlay.setMap(null);
После этого вызывается:
onRemove()
DOM-элементы уничтожаются.
Один из важнейших механизмов OverlayView — объект Projection.
Получение:
const projection =
this.getProjection();
Основные методы:
fromLatLngToDivPixel()
fromDivPixelToLatLng()
Первый переводит координаты в пиксели.
Второй выполняет обратное преобразование.
const latLng =
projection.fromDivPixelToLatLng(
new google.maps.Point(300, 200)
);
Результатом станет объект:
LatLng
Это полезно при создании редакторов карт и инструментов рисования.
Одним из самых распространённых сценариев является вывод собственного HTML.
class HtmlOverlay extends google.maps.OverlayView {
constructor(position, html) {
super();
this.position = position;
this.html = html;
}
onAdd() {
this.div = document.createElement("div");
this.div.innerHTML = this.html;
this.getPanes()
.overlayMouseTarget
.appendChild(this.div);
}
draw() {
const projection =
this.getProjection();
const point =
projection.fromLatLngToDivPixel(
this.position
);
this.div.style.position =
"absolute";
this.div.style.left =
point.x + "px";
this.div.style.top =
point.y + "px";
}
onRemove() {
this.div.remove();
}
}
Вместо стандартных InfoWindow часто используются собственные карточки.
Пример HTML:
<div class="store-card">
<h3>Магазин</h3>
<p>Режим работы: 09:00–21:00</p>
</div>
CSS:
.store-card {
background: white;
padding: 12px;
border-radius: 8px;
box-shadow: 0 2px 10px rgba(0,0,0,.2);
}
Такие карточки могут содержать:
Overlay способен обрабатывать стандартные DOM-события.
Пример:
this.div.addEventListener(
"click",
() => {
console.log("Клик");
}
);
Также доступны:
mouseover
mouseout
mousedown
mouseup
dblclick
contextmenu
Иногда необходимо предотвратить обработку событий картой.
Например:
this.div.addEventListener(
"click",
event => {
event.stopPropagation();
}
);
Это предотвращает запуск событий карты после клика по Overlay.
Поскольку Overlay представляет собой обычный HTML-элемент, доступны любые CSS-анимации.
Пример:
.marker {
animation: pulse 1s infinite;
}
@keyframes pulse {
0% {
transform: scale(1);
}
50% {
transform: scale(1.3);
}
100% {
transform: scale(1);
}
}
Для отображения большого количества объектов часто используется Canvas.
Создание:
const canvas =
document.createElement("canvas");
Добавление:
this.div.appendChild(canvas);
Далее можно использовать стандартный API Canvas:
const ctx = canvas.getContext("2d");
ctx.beginPath();
ctx.arc(
100,
100,
30,
0,
Math.PI * 2
);
ctx.fill();
SVG особенно полезен для:
Пример:
this.div.innerHTML = `
<svg width="100" height="100">
<circle
cx="50"
cy="50"
r="40"
/>
</svg>
`;
Для полной кастомизации маркеров Overlay часто оказывается удобнее стандартного Marker.
Пример:
<div class="custom-marker">
★
</div>
.custom-marker {
font-size: 28px;
color: red;
}
Преимущества:
Каждый Overlay создаёт DOM-узел.
При тысячах объектов возникают проблемы:
Плохой вариант:
5000 Overlay объектов
Лучший вариант:
1 Overlay + Canvas
или
кластеризация
Для временного скрытия:
this.div.style.display = "none";
Показ:
this.div.style.display = "block";
При этом объект остаётся привязанным к карте.
this.div.style.opacity = "0.5";
Либо через CSS:
.overlay {
opacity: 0.5;
}
Используется свойство:
z-index
Пример:
this.div.style.zIndex = 1000;
Большие значения отображаются поверх остальных объектов.
Часто в собственном классе создают дополнительные методы управления.
hide() {
if (this.div) {
this.div.style.visibility =
"hidden";
}
}
show() {
if (this.div) {
this.div.style.visibility =
"visible";
}
}
toggle() {
if (
this.div.style.visibility ===
"hidden"
) {
this.show();
} else {
this.hide();
}
}
Полное удаление и восстановление объекта:
toggleDOM() {
if (this.getMap()) {
this.setMap(null);
} else {
this.setMap(map);
}
}
Такой подход позволяет полностью исключать Overlay из процесса рендеринга.
Использование исторических карт, спутниковых снимков или планов зданий поверх основной карты.
Отображение информации о магазинах, складах, объектах недвижимости и транспортных узлах.
Отрисовка аналитических данных через Canvas или SVG.
Отображение показаний датчиков, телеметрии и мониторинга оборудования.
Размещение диаграмм, счётчиков и индикаторов непосредственно в географическом контексте.
Создание маркеров с несколькими уровнями вложенности, анимациями и динамическим содержимым.
Построение интерфейсов для рисования, перемещения и редактирования
пространственных объектов с использованием обратного преобразования
координат через объект Projection.
Custom Overlays являются одним из самых мощных механизмов Google Maps JavaScript API, позволяя интегрировать произвольный HTML, Canvas и SVG в пространство карты, полностью контролируя процесс отрисовки, позиционирования, взаимодействия с пользователем и управление жизненным циклом отображаемых объектов.