Позиционирование контролов

Контролы (Controls) в Google Maps JavaScript API представляют собой элементы пользовательского интерфейса, размещаемые поверх карты. К стандартным контролам относятся кнопки изменения масштаба, переключатель типа карты, управление полноэкранным режимом, инструмент просмотра улиц и другие элементы. Помимо встроенных компонентов API позволяет создавать и размещать собственные пользовательские контролы в любой части карты.

Грамотное позиционирование контролов является важной частью разработки интерфейса картографических приложений. От расположения элементов управления зависит удобство навигации, доступность функций и внешний вид приложения.


Система расположения контролов

Каждая карта содержит набор специальных контейнеров, привязанных к определённым областям интерфейса. Контролы помещаются именно в эти контейнеры.

Для задания позиции используется перечисление google.maps.ControlPosition.

Пример:

map.controls[google.maps.ControlPosition.TOP_LEFT]

Каждая позиция соответствует определённой области карты.

Схематично расположение выглядит следующим образом:

+--------------------------------------------------+
| TOP_LEFT      TOP_CENTER      TOP_RIGHT          |
|                                                  |
| LEFT_TOP                     RIGHT_TOP           |
|                                                  |
| LEFT_CENTER               RIGHT_CENTER           |
|                                                  |
| LEFT_BOTTOM               RIGHT_BOTTOM           |
|                                                  |
| BOTTOM_LEFT  BOTTOM_CENTER  BOTTOM_RIGHT         |
+--------------------------------------------------+

Перечисление ControlPosition

Основные позиции контролов:

Позиция Расположение
TOP_LEFT Верхний левый угол
TOP_CENTER Верхняя центральная область
TOP_RIGHT Верхний правый угол
LEFT_TOP Левая сторона сверху
LEFT_CENTER Левая сторона по центру
LEFT_BOTTOM Левая сторона снизу
RIGHT_TOP Правая сторона сверху
RIGHT_CENTER Правая сторона по центру
RIGHT_BOTTOM Правая сторона снизу
BOTTOM_LEFT Нижний левый угол
BOTTOM_CENTER Нижняя центральная область
BOTTOM_RIGHT Нижний правый угол

Каждая из этих позиций представляет отдельный контейнер DOM-элементов.


Позиционирование встроенных контролов

Большинство стандартных контролов имеют собственные настройки позиции.

Например, контрол масштабирования можно перенести в правый верхний угол:

const map = new google.maps.Map(
    document.getElementById("map"),
    {
        center: { lat: 55.7558, lng: 37.6176 },
        zoom: 10,

        zoomControl: true,

        zoomControlOptions: {
            position: google.maps.ControlPosition.TOP_RIGHT
        }
    }
);

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


Перемещение переключателя типа карты

Контрол выбора типа карты (MapTypeControl) также поддерживает изменение позиции.

const map = new google.maps.Map(
    document.getElementById("map"),
    {
        mapTypeControl: true,

        mapTypeControlOptions: {
            position: google.maps.ControlPosition.TOP_LEFT
        }
    }
);

По умолчанию расположение зависит от версии API и используемой темы интерфейса, поэтому явное указание позиции обеспечивает предсказуемое поведение.


Позиционирование полноэкранного режима

Контрол полноэкранного отображения карты можно перемещать аналогичным образом.

const map = new google.maps.Map(
    document.getElementById("map"),
    {
        fullscreenControl: true,

        fullscreenControlOptions: {
            position: google.maps.ControlPosition.RIGHT_TOP
        }
    }
);

Такое решение часто используется в приложениях с большим количеством собственных инструментов в верхней части карты.


Позиционирование Street View

Инструмент перехода в режим панорам также поддерживает настройку позиции.

const map = new google.maps.Map(
    document.getElementById("map"),
    {
        streetViewControl: true,

        streetViewControlOptions: {
            position: google.maps.ControlPosition.RIGHT_BOTTOM
        }
    }
);

Перемещение Street View позволяет избежать пересечения с другими элементами интерфейса.


Одновременное позиционирование нескольких контролов

Несколько встроенных контролов могут быть размещены в разных областях карты.

const map = new google.maps.Map(
    document.getElementById("map"),
    {
        zoomControl: true,
        mapTypeControl: true,
        streetViewControl: true,
        fullscreenControl: true,

        zoomControlOptions: {
            position: google.maps.ControlPosition.RIGHT_CENTER
        },

        mapTypeControlOptions: {
            position: google.maps.ControlPosition.TOP_LEFT
        },

        streetViewControlOptions: {
            position: google.maps.ControlPosition.RIGHT_BOTTOM
        },

        fullscreenControlOptions: {
            position: google.maps.ControlPosition.TOP_RIGHT
        }
    }
);

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


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

Пользовательский контрол представляет собой обычный DOM-элемент.

Создадим кнопку сброса масштаба:

const button = document.createElement("button");

button.textContent = "Сбросить масштаб";

button.style.background = "#fff";
button.style.border = "2px solid #ccc";
button.style.padding = "10px";
button.style.cursor = "pointer";

Добавим обработчик:

button.addEventListener("click", () => {
    map.setZoom(8);
});

Теперь элемент можно разместить на карте.


Добавление пользовательского контрола в позицию

Контрол помещается в нужный контейнер через массив map.controls.

map.controls[
    google.maps.ControlPosition.TOP_CENTER
].push(button);

После выполнения кода кнопка появится в верхней центральной части карты.


Работа массива controls

Свойство controls содержит коллекцию контейнеров для всех доступных позиций.

Пример доступа:

const topLeftControls =
    map.controls[
        google.maps.ControlPosition.TOP_LEFT
    ];

Каждая позиция представляет объект типа MVCArray.

Можно добавлять элементы:

topLeftControls.push(button);

Удалять:

topLeftControls.removeAt(0);

Получать количество элементов:

console.log(topLeftControls.getLength());

Получать элемент по индексу:

console.log(topLeftControls.getAt(0));

Порядок отображения контролов

Если несколько элементов добавляются в один контейнер, порядок определяется последовательностью вставки.

Пример:

controls.push(button1);
controls.push(button2);
controls.push(button3);

На экране элементы будут расположены следующим образом:

button1
button2
button3

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


Изменение порядка контролов

Порядок можно изменять программно.

const controls =
    map.controls[
        google.maps.ControlPosition.TOP_LEFT
    ];

const control = controls.removeAt(0);

controls.push(control);

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


Группировка пользовательских контролов

Часто несколько кнопок объединяют в единый контейнер.

const panel = document.createElement("div");

panel.style.display = "flex";
panel.style.flexDirection = "column";

Создание кнопок:

const zoomIn = document.createElement("button");
zoomIn.textContent = "+";

const zoomOut = document.createElement("button");
zoomOut.textContent = "-";

panel.appendChild(zoomIn);
panel.appendChild(zoomOut);

Размещение:

map.controls[
    google.maps.ControlPosition.LEFT_TOP
].push(panel);

Такой подход позволяет создавать панели инструментов любой сложности.


Использование CSS для дополнительного позиционирования

Контейнер карты определяет только общую область размещения. Более точное расположение можно задавать через CSS.

button.style.marginTop = "15px";
button.style.marginLeft = "10px";

Пример:

const control = document.createElement("div");

control.style.margin = "20px";
control.style.padding = "10px";
control.style.background = "#fff";

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


Адаптивное позиционирование

На мобильных устройствах пространство ограничено, поэтому часто используется динамическое изменение расположения контролов.

const position =
    window.innerWidth < 768
        ? google.maps.ControlPosition.BOTTOM_CENTER
        : google.maps.ControlPosition.TOP_RIGHT;

map.controls[position].push(button);

Подобная техника позволяет улучшить удобство использования интерфейса на смартфонах и планшетах.


Перемещение контрола между позициями

Контрол можно удалять из одной области и добавлять в другую.

const oldPosition =
    map.controls[
        google.maps.ControlPosition.TOP_LEFT
    ];

const control = oldPosition.removeAt(0);

Добавление:

map.controls[
    google.maps.ControlPosition.BOTTOM_RIGHT
].push(control);

Такой механизм используется для адаптации интерфейса под различные режимы работы приложения.


Скрытие и повторное отображение контрола

Удаление из контейнера приводит к исчезновению элемента с карты.

const controls =
    map.controls[
        google.maps.ControlPosition.TOP_RIGHT
    ];

const control = controls.removeAt(0);

Для возврата:

controls.push(control);

DOM-элемент сохраняется и может использоваться повторно.


Практические рекомендации по размещению контролов

Верхний левый угол

Подходит для:

  • главного меню;
  • навигационных кнопок;
  • панели инструментов.

Верхний правый угол

Обычно используется для:

  • масштабирования;
  • полноэкранного режима;
  • переключателей режимов отображения.

Нижние области

Часто содержат:

  • информацию о маршруте;
  • статистику;
  • элементы фильтрации.

Центральные области

Используются редко, поскольку перекрывают карту и ухудшают обзор.


Типичная схема интерфейса

Для большинства картографических приложений хорошо подходит следующая конфигурация:

mapTypeControlOptions: {
    position: google.maps.ControlPosition.TOP_LEFT
},

zoomControlOptions: {
    position: google.maps.ControlPosition.RIGHT_TOP
},

fullscreenControlOptions: {
    position: google.maps.ControlPosition.RIGHT_TOP
},

streetViewControlOptions: {
    position: google.maps.ControlPosition.RIGHT_BOTTOM
}

Подобная организация интерфейса соответствует распространённым паттернам современных веб-карт и обеспечивает удобное распределение элементов управления по различным зонам карты.