Позиционирование изображений по координатам

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

Позиционирование изображения по координатам представляет собой процесс размещения графического объекта таким образом, чтобы его границы соответствовали определённой области на поверхности Земли.

Для решения этой задачи в Google Maps JavaScript API применяется механизм оверлеев (Overlay), позволяющий накладывать изображения поверх базовой карты.


Географическая привязка изображения

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

Для этого задаётся прямоугольная область:

  • северная граница (north);
  • южная граница (south);
  • западная граница (west);
  • восточная граница (east).

В API такая область описывается объектом LatLngBounds.

Пример:

const imageBounds = {
    north: 55.7600,
    south: 55.7500,
    east: 37.6300,
    west: 37.6100
};

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

Схематически:

north
 ┌───────────────────┐
 │                   │
 │     ИЗОБРАЖЕНИЕ   │
 │                   │
 └───────────────────┘
south

west             east

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


GroundOverlay

Для размещения изображения на карте предназначен класс 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);

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


Использование объекта LatLngBounds

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

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

или использовать тайловую структуру.

Большие изображения:

  • увеличивают время загрузки;
  • потребляют память;
  • ухудшают плавность масштабирования.

Точность привязки координат

Наиболее сложная часть работы — корректное определение границ изображения.

Ошибки приводят к:

  • смещению объекта;
  • искажению масштаба;
  • несовпадению с дорогами и зданиями.

Обычно координаты получают:

  • из GPS;
  • из GIS-систем;
  • через геодезические измерения;
  • путём ручной калибровки.

Автоматическая подгонка карты под изображение

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

map.fitBounds(bounds);

Полный пример:

const overlay =
    new google.maps.GroundOverlay(
        "images/site-plan.png",
        bounds
    );

overlay.setMap(map);

map.fitBounds(bounds);

Карта автоматически выберет масштаб, при котором всё изображение окажется в зоне видимости.


Создание пользовательского OverlayView

GroundOverlay подходит не всегда. Иногда требуется полный контроль над позиционированием.

Для этого используется класс:

google.maps.OverlayView

Создаётся наследник:

class ImageOverlay
    extends google.maps.OverlayView {

}

Такой подход позволяет:

  • вращать изображения;
  • применять CSS-анимации;
  • использовать SVG;
  • управлять DOM-элементами напрямую.

Реализация OverlayView

Простейшая структура:

class ImageOverlay
    extends google.maps.OverlayView {

    constructor(bounds, image) {
        super();

        this.bounds = bounds;
        this.image = image;
    }

}

Далее реализуются методы жизненного цикла.


Метод onAdd

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

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

Отвечает за вычисление позиции элемента.

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";

}

Именно здесь происходит преобразование географических координат в экранные координаты.


Метод onRemove

Удаление 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
}

Таким образом географические координаты превращаются в координаты внутри контейнера карты.


Использование SVG вместо растровых изображений

Вместо 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, если требуется:

  • анимация;
  • вращение;
  • пользовательское масштабирование;
  • сложное взаимодействие с DOM.

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

Минимизировать размер файлов, особенно при работе с большим количеством оверлеев.

Тщательно проверять координатные границы, поскольку даже небольшая ошибка в значениях north, south, east и west приводит к заметному смещению изображения на карте.