Mapbox GL JS предоставляет систему контролов (controls), которая позволяет управлять элементами интерфейса карты — масштабированием, навигацией, геолокацией и пользовательскими компонентами. Одним из ключевых аспектов работы с контролами является их позиционирование внутри контейнера карты и управление порядком отображения.
Контролы встраиваются в DOM карты через единый контейнер, разделённый на четыре логические области: верхний левый угол, верхний правый, нижний левый и нижний правый. Каждый контрол при добавлении получает одно из этих расположений, определяющее его визуальное место.
Метод добавления контролов:
map.addControl(control, position);
Параметр position принимает одно из фиксированных
значений:
top-lefttop-rightbottom-leftbottom-rightКаждая зона соответствует отдельному DOM-контейнеру внутри карты. При добавлении контрол автоматически помещается в соответствующую группу.
Внутри Mapbox GL JS каждая зона реализована как отдельный блок с классом вида:
mapboxgl-ctrl-top-leftmapboxgl-ctrl-top-rightmapboxgl-ctrl-bottom-leftmapboxgl-ctrl-bottom-rightЭти контейнеры располагаются поверх карты и используют flex-раскладку по вертикали.
Контролы внутри одной зоны отображаются в порядке их добавления:
map.addControl(new mapboxgl.NavigationControl(), 'top-right');
map.addControl(new mapboxgl.FullscreenControl(), 'top-right');
В этом случае NavigationControl окажется выше в
DOM-структуре (и визуально выше/левее в зависимости от
flex-направления), а FullscreenControl будет добавлен
ниже.
Порядок можно использовать как инструмент управления приоритетом интерфейсных элементов без дополнительного CSS.
Часто используемые контролы:
map.addControl(new mapboxgl.NavigationControl(), 'top-right');
map.addControl(new mapboxgl.GeolocateControl(), 'top-right');
map.addControl(new mapboxgl.FullscreenControl(), 'top-right');
map.addControl(new mapboxgl.ScaleControl(), 'bottom-left');
Особенности поведения:
Каждый из них следует общей системе позиционирования и не требует дополнительной настройки координат.
Контейнеры контролов имеют базовую структуру:
<div class="mapboxgl-ctrl-top-right">
<div class="mapboxgl-ctrl-group">
<!-- controls -->
</div>
</div>
Ключевые классы:
mapboxgl-ctrl — базовый класс любого контролаmapboxgl-ctrl-group — группа кнопок (например, zoom +
rotate)mapboxgl-ctrl-top-* — позиционные контейнерыСтили по умолчанию используют абсолютное позиционирование относительно карты и z-index для перекрытия тайлов и слоёв.
Контролы располагаются поверх canvas-контейнера карты. Их порядок определяется:
Если требуется, чтобы кастомный интерфейс перекрывал контролы, необходимо учитывать, что стандартные контролы имеют достаточно высокий z-index, поэтому простое добавление HTML-элемента может быть недостаточным.
Для создания собственного контрола используется интерфейс:
const customControl = {
onAdd(map) {
this._map = map;
this._container = document.createElement('div');
this._container.className = 'mapboxgl-ctrl mapboxgl-ctrl-group';
this._container.textContent = 'Custom';
return this._container;
},
onRemove() {
this._container.parentNode.removeChild(this._container);
this._map = undefined;
}
};
map.addControl(customControl, 'bottom-right');
Кастомный контрол полностью подчиняется той же системе позиционирования, что и встроенные элементы.
Контролы можно удалять и перемещать:
map.removeControl(control);
map.addControl(control, 'bottom-left');
Это позволяет динамически менять интерфейс в зависимости от состояния приложения, например:
Система имеет фиксированную модель из четырёх зон. Нельзя напрямую
задать произвольные координаты (например, центр карты или произвольный
пиксельный offset) через addControl.
Попытки изменить позиционирование через внутренние DOM-структуры (например, через приватные контейнеры карты) приводят к нестабильности при обновлениях библиотеки.
Для адаптивных интерфейсов используется комбинация JavaScript и CSS:
function updateControlsPosition() {
const isMobile = window.innerWidth < 600;
map.removeControl(nav);
map.addControl(nav, isMobile ? 'bottom-right' : 'top-right');
}
Такой подход позволяет перераспределять интерфейсные элементы без пересоздания карты.
Дополнительно часто применяются медиазапросы для изменения внешнего вида контейнеров:
.mapboxgl-ctrl-top-right {
margin-top: 10px;
margin-right: 10px;
}
Несколько контролов могут быть визуально объединены в одну группу
через mapboxgl-ctrl-group. Это влияет только на внешний
вид, но не на позиционирование:
Пример:
map.addControl(new mapboxgl.NavigationControl(), 'top-left');
map.addControl(new mapboxgl.FullscreenControl(), 'top-left');
При этом каждый контрол будет в своей группе, если не объединён вручную.
При изменении масштаба карты или её контейнера контролы:
Это важно при работе с responsive layout, особенно при изменении высоты/ширины контейнера карты динамически.
Контролы добавляются только после инициализации объекта карты. При
попытке добавить контрол до события load возможны
некорректные состояния DOM.
Типичный безопасный паттерн:
map.on('load', () => {
map.addControl(new mapboxgl.NavigationControl(), 'top-right');
});
Позиционирование при этом полностью определяется моментом добавления, а не порядком объявления.
В некоторых случаях требуется временно скрывать или менять позицию контролов без удаления всей карты. Это достигается через:
removeControladdControldisplay: none на контейнерах
.mapboxgl-ctrl-*Второй вариант предпочтительнее, так как сохраняет внутреннее состояние контрола.
Контейнер карты имеет структуру:
map container
Контролы всегда находятся выше canvas слоя, но ниже пользовательских overlay-элементов, если те добавлены отдельно в DOM.
Позиционирование контролов в Mapbox GL JS строится на жёстко заданной четырёхзонной модели, порядке добавления и стандартной DOM-структуре, что позволяет предсказуемо управлять интерфейсом без необходимости глубокой модификации внутреннего устройства карты.