В MapLibre GL JS контролы представляют собой расширения интерфейса
карты, добавляющие интерактивные элементы управления: масштабирование,
поворот, геолокацию, масштабную линейку, пользовательские панели. Каждый
контрол реализует единый контракт жизненного цикла и подключается к
экземпляру карты через addControl, а удаляется через
removeControl.
Удаление контролов — это не просто визуальное скрытие элемента, а полноценное отсоединение логики, DOM-узлов и обработчиков событий от экземпляра карты.
Контрол удаляется с карты вызовом метода:
map.removeControl(control);
где control — это ранее добавленный объект, реализующий
интерфейс IControl.
Ключевой момент: для удаления требуется ссылка на тот же экземпляр контролла, который был добавлен. Попытка удалить новый объект с аналогичной конфигурацией не приведёт к эффекту, так как идентичность контролов определяется по ссылке.
Практика управления контролами всегда предполагает сохранение экземпляров:
const navigationControl = new maplibregl.NavigationControl();
map.addControl(navigationControl);
// позже
map.removeControl(navigationControl);
Если ссылка теряется, удалить контрол стандартными средствами невозможно без обходных решений через DOM, что нарушает модель управления библиотекой.
Каждый контрол реализует два ключевых метода:
onAdd(map) — вызывается при добавленииonRemove(map) — вызывается при удаленииПри вызове removeControl происходит следующая
последовательность:
control.onRemove(map)Пример структуры пользовательского контролла:
class CustomControl {
onAdd(map) {
this._map = map;
this._container = document.createElement('div');
this._container.className = 'custom-control';
this._container.textContent = 'Control';
return this._container;
}
onRemove() {
this._map = undefined;
this._container = undefined;
}
}
Удаление такого контролла автоматически инициирует
onRemove, что позволяет корректно освободить ресурсы.
Стандартные контролы MapLibre создаются как отдельные экземпляры и могут быть удалены аналогично пользовательским.
const nav = new maplibregl.NavigationControl();
map.addControl(nav);
// удаление
map.removeControl(nav);
const scale = new maplibregl.ScaleControl();
map.addControl(scale);
// удаление
map.removeControl(scale);
const geolocate = new maplibregl.GeolocateControl();
map.addControl(geolocate);
map.removeControl(geolocate);
Важно учитывать, что контролы, взаимодействующие с геолокацией или
событиями устройства, должны корректно завершать активные процессы в
onRemove.
Контрол атрибуции часто добавляется автоматически при создании карты. Он может быть отключён при инициализации:
const map = new maplibregl.Map({
container: 'map',
style: 'style.json',
attributionControl: false
});
Если контрол добавлен явно:
const attribution = new maplibregl.AttributionControl();
map.addControl(attribution);
то он удаляется стандартным способом:
map.removeControl(attribution);
Следует учитывать, что повторное добавление атрибуции может создавать визуально дублирующиеся элементы, если управление не централизовано.
Типовые проблемы возникают из-за неправильного управления ссылками и состоянием:
map.addControl(new maplibregl.NavigationControl());
// удалить невозможно без сохранённой ссылки
Решение заключается в сохранении экземпляра до добавления.
Попытка удалить уже удалённый контрол обычно не приводит к критической ошибке, но может вызывать неконсистентность состояния, если внешний код продолжает взаимодействовать с DOM-элементами контролла.
Если контрол не был добавлен, вызов removeControl не
имеет эффекта. Внутренние проверки MapLibre предотвращают разрушение
состояния карты, однако логика приложения может оказаться
несогласованной.
В интерфейсах с переключаемыми режимами карты контролы часто добавляются и удаляются в зависимости от состояния приложения.
let scaleControl = null;
function enableScale() {
if (!scaleControl) {
scaleControl = new maplibregl.ScaleControl();
map.addControl(scaleControl);
}
}
function disableScale() {
if (scaleControl) {
map.removeControl(scaleControl);
scaleControl = null;
}
}
Такой подход обеспечивает предсказуемое управление состоянием и исключает утечки DOM-элементов.
Контролы в MapLibre GL JS могут быть размещены в разных углах карты
(top-left, top-right,
bottom-left, bottom-right). Удаление контролла
не зависит от его позиции, однако влияет на перерасчёт layout
контейнера.
map.addControl(new maplibregl.NavigationControl(), 'top-right');
Удаление:
map.removeControl(navigationControl);
После удаления контейнер позиции автоматически пересчитывается, и оставшиеся контролы сдвигаются без пустых слотов.
При создании сложных интерфейсов контрол может содержать вложенные элементы, таймеры, подписки на события карты.
class PanelControl {
onAdd(map) {
this._map = map;
this._container = document.createElement('div');
this._handler = () => {
// обработка события
};
map.on('move', this._handler);
return this._container;
}
onRemove() {
this._map.off('move', this._handler);
this._handler = null;
this._container = null;
}
}
Удаление такого контролла должно гарантировать:
При вызове:
map.remove();
все добавленные контролы автоматически удаляются. В этом случае
removeControl вызывать не требуется, так как карта
инициирует полный цикл очистки:
onRemove для каждогоВ крупных приложениях контролы часто управляются через централизованные менеджеры:
Такой подход позволяет синхронизировать UI и состояние карты, избегая ситуаций, когда контрол существует в DOM, но уже не связан с картой.
Хотя порядок удаления контролов обычно не критичен, в случаях зависимых контролов (например, панель управления слоями и фильтрами) важно соблюдать последовательность:
Это предотвращает обращения к уже несуществующим API карты.
Если onRemove генерирует исключение, удаление контролла
может быть частично завершено, при этом DOM-элемент уже будет удалён.
Это создаёт ситуацию рассогласованного состояния.
Поэтому внутри onRemove обычно избегаются потенциально
опасные операции без проверки наличия ссылок:
onRemove() {
if (this._map) {
this._map.off('event', this._handler);
}
}