Одной из важных возможностей Google Maps JavaScript API является отображение пользовательской графики поверх карты. Вместо стандартных маркеров часто используются логотипы, схемы зданий, планы территорий, исторические карты, спутниковые снимки, рекламные баннеры или любые другие изображения, которые необходимо привязать к конкретным географическим координатам.
Позиционирование изображения по координатам представляет собой процесс размещения графического объекта таким образом, чтобы его границы соответствовали определённой области на поверхности Земли.
Для решения этой задачи в Google Maps JavaScript API применяется механизм оверлеев (Overlay), позволяющий накладывать изображения поверх базовой карты.
Любое изображение на карте должно быть связано с набором координат.
Для этого задаётся прямоугольная область:
В API такая область описывается объектом
LatLngBounds.
Пример:
const imageBounds = {
north: 55.7600,
south: 55.7500,
east: 37.6300,
west: 37.6100
};
В данном случае изображение будет растянуто между указанными координатами.
Схематически:
north
┌───────────────────┐
│ │
│ ИЗОБРАЖЕНИЕ │
│ │
└───────────────────┘
south
west east
Карта автоматически вычисляет размеры изображения на каждом уровне масштабирования.
Для размещения изображения на карте предназначен класс
google.maps.GroundOverlay.
Он позволяет:
Общий синтаксис:
const overlay = new google.maps.GroundOverlay(
imageUrl,
bounds
);
overlay.setMap(map);
Где:
imageUrl — путь к изображению;bounds — координатные границы;map — экземпляр карты.Перед добавлением изображения создаётся карта.
const map = new google.maps.Map(
document.getElementById("map"),
{
center: {
lat: 55.7558,
lng: 37.6176
},
zoom: 15
}
);
HTML-контейнер:
<div id="map"></div>
Стили:
#map {
width: 100%;
height: 600px;
}
После определения карты создаётся оверлей.
const imageBounds = {
north: 55.7600,
south: 55.7500,
east: 37.6300,
west: 37.6100
};
const overlay = new google.maps.GroundOverlay(
"images/plan.png",
imageBounds
);
overlay.setMap(map);
После загрузки изображение появится в заданной области.
Границы можно задавать через специальный класс.
const bounds = new google.maps.LatLngBounds(
{ lat: 55.7500, lng: 37.6100 },
{ lat: 55.7600, lng: 37.6300 }
);
Создание оверлея:
const overlay = new google.maps.GroundOverlay(
"images/photo.png",
bounds
);
overlay.setMap(map);
Такой подход часто используется при динамическом расчёте координат.
GroundOverlay поддерживает управление прозрачностью.
const overlay = new google.maps.GroundOverlay(
"images/scheme.png",
bounds
);
overlay.setOpacity(0.5);
overlay.setMap(map);
Значения:
0 — полностью прозрачное
0.5 — полупрозрачное
1 — непрозрачное
Пример:
overlay.setOpacity(0.75);
Это полезно при наложении схемы поверх спутникового снимка.
Прозрачность может изменяться динамически.
slider.addEventListener("input", event => {
overlay.setOpacity(
Number(event.target.value)
);
});
HTML:
<input
type="range"
min="0"
max="1"
step="0.1"
/>
Такой механизм часто применяется в ГИС-приложениях.
Чтобы скрыть изображение, используется метод:
overlay.setMap(null);
Пример:
button.addEventListener("click", () => {
overlay.setMap(null);
});
Изображение исчезает, но объект остаётся в памяти.
Если требуется вернуть изображение:
overlay.setMap(map);
Пример переключателя:
let visible = true;
button.addEventListener("click", () => {
visible = !visible;
overlay.setMap(
visible ? map : null
);
});
Метод:
overlay.getMap();
Пример:
console.log(
overlay.getMap()
);
Возвращает:
null.Иногда необходимо загружать другую графику без пересоздания карты.
Создание нового оверлея:
overlay.setMap(null);
overlay = new google.maps.GroundOverlay(
"images/new-image.png",
bounds
);
overlay.setMap(map);
Например:
Одна из наиболее распространённых задач — наложение старых карт на современную местность.
const historicOverlay =
new google.maps.GroundOverlay(
"images/map1910.jpg",
bounds
);
historicOverlay.setMap(map);
После подбора координат можно визуально сравнивать изменения территории.
Часто требуется отображать специализированные изображения:
Пример:
const droneImage =
new google.maps.GroundOverlay(
"images/drone.png",
bounds
);
droneImage.setMap(map);
При использовании файлов большого размера необходимо учитывать производительность.
Нежелательно:
15000 × 15000 px
20000 × 20000 px
Лучше:
2048 × 2048 px
4096 × 4096 px
или использовать тайловую структуру.
Большие изображения:
Наиболее сложная часть работы — корректное определение границ изображения.
Ошибки приводят к:
Обычно координаты получают:
После добавления изображения карту можно центрировать на его области.
map.fitBounds(bounds);
Полный пример:
const overlay =
new google.maps.GroundOverlay(
"images/site-plan.png",
bounds
);
overlay.setMap(map);
map.fitBounds(bounds);
Карта автоматически выберет масштаб, при котором всё изображение окажется в зоне видимости.
GroundOverlay подходит не всегда. Иногда требуется полный контроль над позиционированием.
Для этого используется класс:
google.maps.OverlayView
Создаётся наследник:
class ImageOverlay
extends google.maps.OverlayView {
}
Такой подход позволяет:
Простейшая структура:
class ImageOverlay
extends google.maps.OverlayView {
constructor(bounds, image) {
super();
this.bounds = bounds;
this.image = image;
}
}
Далее реализуются методы жизненного цикла.
Вызывается при добавлении оверлея.
onAdd() {
this.div = document.createElement("div");
this.div.style.position =
"absolute";
const img =
document.createElement("img");
img.src = this.image;
img.style.width = "100%";
img.style.height = "100%";
this.div.appendChild(img);
const panes = this.getPanes();
panes.overlayLayer.appendChild(
this.div
);
}
Отвечает за вычисление позиции элемента.
draw() {
const projection =
this.getProjection();
const sw =
projection.fromLatLngToDivPixel(
this.bounds.getSouthWest()
);
const ne =
projection.fromLatLngToDivPixel(
this.bounds.getNorthEast()
);
this.div.style.left =
sw.x + "px";
this.div.style.top =
ne.y + "px";
this.div.style.width =
(ne.x - sw.x) + "px";
this.div.style.height =
(sw.y - ne.y) + "px";
}
Именно здесь происходит преобразование географических координат в экранные координаты.
Удаление DOM-элемента.
onRemove() {
if (this.div) {
this.div.parentNode.removeChild(
this.div
);
this.div = null;
}
}
Метод автоматически вызывается после:
overlay.setMap(null);
Внутри OverlayView используется объект проекции.
Получение:
const projection =
overlay.getProjection();
Преобразование:
projection.fromLatLngToDivPixel(
position
);
Результат:
{
x: 512,
y: 278
}
Таким образом географические координаты превращаются в координаты внутри контейнера карты.
Вместо PNG или JPG можно использовать SVG.
const overlay =
new google.maps.GroundOverlay(
"images/schema.svg",
bounds
);
Преимущества:
На карту можно добавлять множество оверлеев.
const overlays = [];
data.forEach(item => {
const overlay =
new google.maps.GroundOverlay(
item.url,
item.bounds
);
overlay.setMap(map);
overlays.push(overlay);
});
Применяется для:
При использовании OverlayView возможно управлять слоями
через CSS.
this.div.style.zIndex = 100;
Пример:
roadLayer.style.zIndex = 1;
buildingLayer.style.zIndex = 2;
labelLayer.style.zIndex = 3;
Чем выше значение, тем выше располагается изображение.
buildingPlan.png
Привязка схемы этажей к территории объекта.
old-city-map.jpg
Сравнение разных периодов развития местности.
drone-photo.jpg
Анализ состояния территорий.
geology-layer.png
Отображение специализированных тематических слоёв.
utility-network.png
Визуализация коммуникаций и инфраструктуры.
Использовать GroundOverlay, если необходимо просто разместить изображение по координатам.
Использовать OverlayView, если требуется:
Сохранять пропорции изображения, чтобы избежать визуальных искажений.
Минимизировать размер файлов, особенно при работе с большим количеством оверлеев.
Тщательно проверять координатные границы, поскольку
даже небольшая ошибка в значениях north,
south, east и west приводит к
заметному смещению изображения на карте.