Удаление объектов

Работа с объектами в Mapbox GL JS строится вокруг строгой иерархии: карта → источники (sources) → слои (layers) → визуальные сущности (markers, popups, images). Удаление элементов требует соблюдения этой структуры, поскольку зависимости между компонентами жёстко связаны.

Ключевое правило управления состоянием карты:

Сначала удаляются слои, затем источники данных. Нарушение порядка приводит к ошибкам вида Source cannot be removed while layer is using it.


Удаление слоёв (Layers)

Слои отвечают за визуализацию данных. Удаление слоя не затрагивает источник данных, но освобождает рендеринг.

map.removeLayer('layer-id');

Особенности удаления слоёв

  • слой должен существовать на карте;
  • перед удалением необходимо убедиться, что он не используется другими слоями (в случае зависимых выражений);
  • удаление слоя не очищает данные GeoJSON или векторный источник.

Проверка существования слоя

if (map.getLayer('layer-id')) {
    map.removeLayer('layer-id');
}

Удаление источников данных (Sources)

Источники данных являются фундаментом визуализации. Они могут быть GeoJSON, vector tiles, raster tiles и др.

map.removeSource('source-id');

Критическое правило зависимости

Источник нельзя удалить, если он используется хотя бы одним слоем.

Правильная последовательность:

if (map.getLayer('layer-id')) {
    map.removeLayer('layer-id');
}

if (map.getSource('source-id')) {
    map.removeSource('source-id');
}

Частая ошибка

Попытка удаления источника до слоя вызывает исключение:

The source "source-id" cannot be removed while layer "layer-id" is using it

Удаление объектов Marker

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

marker.remove();

Характеристики удаления маркера

  • удаляется DOM-узел;
  • освобождаются все привязанные события;
  • маркер перестаёт отображаться, но ссылка на объект остаётся в памяти.

Управление коллекцией маркеров

При работе с множественными маркерами требуется явное хранение ссылок:

markers.forEach(marker => marker.remove());
markers = [];

Удаление всплывающих окон (Popups)

Popups также являются DOM-объектами, привязанными к карте.

popup.remove();

Поведение при удалении

  • закрывает окно;
  • удаляет DOM-контейнер;
  • прекращает обработку событий.

Удаление GeoJSON-объектов через обновление данных

GeoJSON-источники не позволяют удалять отдельные features напрямую. Вместо этого применяется перезапись данных.

Полное очищение слоя данных

const source = map.getSource('geojson-source');

source.setData({
    type: 'FeatureCollection',
    features: []
});

Удаление конкретного объекта

const updated = geojson.features.filter(f => f.id !== targetId);

map.getSource('geojson-source').setData({
    type: 'FeatureCollection',
    features: updated
});

Принцип

GeoJSON-источник всегда перерисовывается целиком, что делает его удаление логически равным замене состояния.


Управление изображениями в стиле (Images / Sprites)

Добавленные изображения можно удалить из стиля карты:

map.removeImage('image-id');

Условия удаления

  • изображение не должно использоваться в слоях типа symbol;
  • предварительно необходимо удалить зависимые слои.

Очистка событий

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

map.off('click', 'layer-id', handler);
map.off('mousemove', handler);

Типичная проблема

Утечка памяти возникает при отсутствии явного удаления обработчиков, особенно при динамической перерисовке слоёв.


Удаление слоя с зависимыми ресурсами (правильный порядок очистки)

Полный цикл удаления связанного набора объектов:

if (map.getLayer('layer-id')) {
    map.removeLayer('layer-id');
}

if (map.getSource('source-id')) {
    map.removeSource('source-id');
}

if (map.hasImage('image-id')) {
    map.removeImage('image-id');
}

Полное уничтожение карты

Удаление всей карты освобождает все ресурсы WebGL и DOM.

map.remove();

Последствия выполнения

  • уничтожается WebGL контекст;
  • удаляются все слои и источники;
  • очищаются события;
  • DOM-контейнер карты перестаёт функционировать.

Важная особенность

После вызова map.remove() любые обращения к объекту карты становятся недопустимыми и приводят к ошибкам выполнения.


Управление динамическими слоями и источниками

При частой перерисовке интерфейса используется стратегия “создать → обновить → удалить”.

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

if (map.getLayer('temp-layer')) {
    map.removeLayer('temp-layer');
}

if (map.getSource('temp-source')) {
    map.removeSource('temp-source');
}

map.addSource('temp-source', {
    type: 'geojson',
    data: geojsonData
});

map.addLayer({
    id: 'temp-layer',
    type: 'circle',
    source: 'temp-source'
});

Принцип

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


Особенности удаления векторных и растровых слоёв

Векторные слои

  • зависят от source;
  • требуют строгого порядка удаления.

Растровые слои

  • часто используют tile sources;
  • удаляются аналогично, но без необходимости обработки GeoJSON.
map.removeLayer('raster-layer');
map.removeSource('raster-source');

Работа с feature-state при удалении

Feature-state не удаляется автоматически при удалении слоя.

map.setFeatureState(
    { source: 'source-id', id: featureId },
    {}
);

Для очистки состояния используется перезапись или удаление source.


Типовые ошибки при удалении объектов

  • удаление source до layer;
  • отсутствие проверки существования объектов;
  • сохранение ссылок на удалённые маркеры;
  • повторное обращение к map после map.remove();
  • утечки событий из-за отсутствия map.off.

Стратегии безопасного удаления

  • проверка через getLayer и getSource;
  • хранение всех созданных объектов в структурах управления состоянием;
  • централизованное удаление через единый cleanup-функционал;
  • явное управление жизненным циклом DOM-объектов;
  • синхронное удаление зависимостей в правильном порядке.