Интерфейс управления картой в MapLibre GL JS построен вокруг концепции контролов (controls) — модульных UI-компонентов, которые подключаются к экземпляру карты и расширяют его функциональность без изменения базовой логики рендеринга. Контролы добавляются поверх canvas и взаимодействуют с экземпляром карты через стандартный программный интерфейс, обеспечивая единообразие поведения и внешнего вида.
Контрол в MapLibre GL JS представляет собой объект, реализующий минимальный контракт:
onAdd(map) — вызывается при добавлении на
картуonRemove() — вызывается при удаленииgetDefaultPosition() — определяет позицию
по умолчаниюКонтролы не зависят от конкретной реализации карты и взаимодействуют с ней через публичное API. Это позволяет создавать переиспользуемые компоненты, которые можно подключать к разным проектам без модификации ядра.
Каждый контрол добавляется через:
map.addControl(control, position);
Параметр position определяет размещение интерфейса:
top-lefttop-rightbottom-leftbottom-rightЕсли позиция не указана, используется значение, возвращаемое
getDefaultPosition().
NavigationControl объединяет основные инструменты навигации: зум, поворот и наклон.
const nav = new maplibregl.NavigationControl({
visualizePitch: true,
showCompass: true
});
map.addControl(nav, 'top-right');
Функциональность:
NavigationControl особенно полезен в интерактивных сценах, где требуется пространственная навигация, а не только 2D-панорама.
ScaleControl отображает линейку масштаба, автоматически пересчитываемую при изменении зума и широты.
const scale = new maplibregl.ScaleControl({
maxWidth: 120,
unit: 'metric'
});
map.addControl(scale, 'bottom-left');
Параметры:
maxWidth — максимальная ширина линейки в
пикселях
unit — единицы измерения:
metricimperialnauticalScaleControl опирается на проекцию карты и геодезические расчёты, обеспечивая корректность отображения расстояний при разных уровнях масштабирования.
AttributionControl отвечает за отображение юридической информации о данных карты.
const attribution = new maplibregl.AttributionControl({
compact: true,
customAttribution: 'Данные: OpenStreetMap contributors'
});
map.addControl(attribution);
Особенности:
compact)Контрол динамически обновляется при изменении стиля карты, анализируя источники данных в слоях и тайлах.
GeolocateControl использует браузерный Geolocation API для получения координат пользователя и синхронизации карты с текущим положением.
const geolocate = new maplibregl.GeolocateControl({
positionOptions: {
enableHighAccuracy: true
},
trackUserLocation: true,
showAccuracyCircle: true
});
map.addControl(geolocate, 'top-right');
Режимы работы:
Контрол взаимодействует с устройствами GPS, Wi-Fi позиционированием и
другими источниками браузера, возвращая объект
GeolocationPosition.
FullScreenControl переключает карту в полноэкранный режим с использованием Fullscreen API браузера.
const fullscreen = new maplibregl.FullscreenControl();
map.addControl(fullscreen, 'top-right');
Поведение:
Контрол учитывает ограничения браузеров, включая необходимость пользовательского действия для активации полноэкранного режима.
Контролы группируются по углам контейнера карты. Внутри каждой позиции они располагаются в порядке добавления.
map.addControl(new maplibregl.NavigationControl(), 'top-left');
map.addControl(new maplibregl.ScaleControl(), 'bottom-left');
map.addControl(new maplibregl.GeolocateControl(), 'top-left');
Порядок важен при комбинировании нескольких контролов в одной зоне интерфейса: последний добавленный отображается выше в DOM-иерархии.
Каждый контрол проходит стандартные стадии:
onAdd(map)onRemove() при удаленииУдаление осуществляется через:
map.removeControl(control);
При удалении контрол обязан освободить DOM-узлы и снять все обработчики событий, чтобы избежать утечек памяти.
Интерфейс IControl позволяет создавать собственные
элементы управления.
Базовая структура:
class CustomControl {
onAdd(map) {
this._map = map;
this._container = document.createElement('div');
this._container.className = 'maplibregl-ctrl custom-control';
const button = document.createElement('button');
button.textContent = 'Центр';
button.oncl ick = () => {
map.setCenter([0, 0]);
};
this._container.appendChild(button);
return this._container;
}
onRemove() {
this._container.parentNode.removeChild(this._container);
this._map = undefined;
}
getDefaultPosition() {
return 'top-right';
}
}
map.addControl(new CustomControl());
Ключевые аспекты:
maponRemoveКонтролы часто подписываются на события карты:
onAdd(map) {
this._map = map;
this._map.on('move', this._update.bind(this));
}
Типичные события:
movezoomrotateloadПри использовании событий важно обеспечивать отписку:
onRemove() {
this._map.off('move', this._update);
}
Все стандартные контролы используют CSS-классы:
maplibregl-ctrlmaplibregl-ctrl-groupmaplibregl-ctrl-iconПереопределение внешнего вида выполняется через CSS:
.maplibregl-ctrl button {
width: 36px;
height: 36px;
background-color: #1e1e1e;
color: #fff;
}
Контейнер контролов не изолирован, поэтому стили наследуются из глобального DOM.
Контролы могут добавляться динамически:
if (userHasPermission) {
map.addControl(new maplibregl.NavigationControl());
}
И удаляться при изменении состояния приложения:
map.removeControl(navControl);
Это позволяет адаптировать интерфейс под роль пользователя или контекст устройства (мобильное/десктоп).
Контролы не имеют встроенного механизма координации, но могут взаимодействовать через общий экземпляр карты:
Пример синхронизации:
geolocate.on('geolocate', (e) => {
map.flyTo({
center: [e.coords.longitude, e.coords.latitude],
zoom: 14
});
});
Такая модель сохраняет слабую связанность компонентов и упрощает масштабирование интерфейса управления.