Удаление фигур

Работа с объектами на карте в Google Maps JavaScript API строится вокруг принципа явного управления слоями: каждый графический элемент (маркер, линия, многоугольник, окружность) хранит ссылку на карту через метод setMap. Удаление фигур в этой архитектуре не является «автоматическим» процессом — оно представляет собой разрыв связи объекта с экземпляром карты и последующую очистку внутренних ссылок, чтобы предотвратить утечки памяти и сохранить корректное состояние отображения.

Все основные примитивы API наследуют общий интерфейс MVCObject и поддерживают метод:

setMap(null)

Передача null в setMap полностью удаляет объект с карты, не уничтожая сам экземпляр в памяти JavaScript. Это ключевая особенность: объект перестаёт рендериться, но остаётся доступным, пока на него существуют ссылки.

Пример универсального удаления:

marker.setMap(null);
polyline.setMap(null);
polygon.setMap(null);
circle.setMap(null);

Такой подход применяется ко всем overlay-объектам, которые напрямую привязаны к карте.


Удаление маркеров

Маркер является наиболее частым объектом, который требуется удалять динамически. При работе с коллекциями маркеров важно учитывать, что API не предоставляет автоматического «менеджера» удаления — управление списками выполняется вручную.

Удаление одиночного маркера

marker.setMap(null);
marker = null;

Обнуление переменной после удаления снижает вероятность удержания объекта в памяти через замыкания.

Удаление массива маркеров

markers.forEach(marker => marker.setMap(null));
markers.length = 0;

Очистка массива обязательна, так как сам API не отслеживает коллекции.


Удаление линий (Polyline)

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

polyline.setMap(null);
polyline = null;

При работе с несколькими линиями:

polylines.forEach(line => line.setMap(null));
polylines = [];

Если координаты пересоздаются динамически, важно отдельно очищать массив LatLng, чтобы избежать накопления данных:

path.length = 0;

Удаление многоугольников (Polygon)

Многоугольники могут содержать сложные структуры вершин, включая редактируемые контуры. Удаление затрагивает только визуальное представление, но не обязательно связанные данные.

polygon.setMap(null);
polygon = null;

Для коллекции:

polygons.forEach(p => p.setMap(null));
polygons = [];

Если используется редактирование (editable: true), необходимо учитывать, что изменения в вершинах могут быть подписаны через события. В таком случае дополнительно требуется очистка слушателей.


Удаление окружностей (Circle)

Окружности представляют собой объект с центром и радиусом. Удаление выполняется стандартным способом:

circle.setMap(null);
circle = null;

При массовом удалении:

circles.forEach(c => c.setMap(null));
circles = [];

Очистка событий при удалении фигур

Каждый overlay может иметь привязанные обработчики событий через addListener. Удаление объекта с карты не гарантирует автоматическое удаление слушателей.

const listener = google.maps.event.addListener(marker, "click", () => {
  // логика
});

При удалении объекта рекомендуется явно очищать слушатели:

google.maps.event.clearInstanceListeners(marker);
marker.setMap(null);
marker = null;

Игнорирование этого шага может приводить к сохранению ссылок на удалённые объекты.


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

Отдельный механизм представляет Data Layer, который работает с геометриями GeoJSON.

Удаление объектов выполняется иначе, чем у overlay:

map.data.remove(feature);

Полная очистка слоя:

map.data.forEach(feature => {
  map.data.remove(feature);
});

Важно учитывать, что Data Layer управляется внутри карты, поэтому setMap(null) здесь не применяется.


Полная очистка всех фигур с карты

В случаях, когда на карте создаётся множество динамических объектов, используется централизованный подход управления:

function clearAll() {
  markers.forEach(m => m.setMap(null));
  polylines.forEach(l => l.setMap(null));
  polygons.forEach(p => p.setMap(null));
  circles.forEach(c => c.setMap(null));

  markers = [];
  polylines = [];
  polygons = [];
  circles = [];
}

Такая структура предотвращает накопление «осиротевших» объектов и упрощает управление состоянием карты.


Особенности жизненного цикла объектов

Удаление через setMap(null) не уничтожает объект мгновенно. Внутри API происходит:

  • разрыв связи с DOM-слоем карты;
  • удаление визуального представления;
  • сохранение JS-объекта до сборки мусора;
  • удержание внутренних ссылок до очистки слушателей.

Поэтому корректное освобождение ресурсов включает три шага:

  1. setMap(null)
  2. clearInstanceListeners
  3. удаление внешних ссылок (массивы, переменные)

Частые ошибки при удалении фигур

Неполная очистка приводит к накоплению объектов и ухудшению производительности карты.

Типичные проблемы:

  • сохранение ссылок в массивах без очистки;
  • отсутствие clearInstanceListeners;
  • повторное создание объектов вместо переиспользования;
  • попытка удалить объект через delete вместо setMap(null);
  • игнорирование Data Layer при смешанном использовании слоёв.

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

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

function removeLayer(layer) {
  layer.items.forEach(item => item.setMap(null));
  layer.items = [];
}

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


Поведение при перерисовке карты

При изменении центра или масштаба карты объекты не удаляются автоматически. Даже при полном изменении состояния карты overlay-объекты остаются в памяти и продолжают быть привязанными к экземпляру карты до явного удаления через setMap(null).

Это особенно важно при:

  • переключении между наборами данных;
  • построении маршрутов;
  • динамической фильтрации геометрий;
  • обновлении слоёв в реальном времени.

Оптимизация удаления большого количества объектов

При массовом удалении (сотни и тысячи фигур) рекомендуется снижать нагрузку:

  • сначала отключать карту от обновлений;
  • выполнять удаление в цикле без промежуточного рендеринга;
  • очищать массивы после завершения операции.
function bulkRemove(items) {
  for (let i = 0; i < items.length; i++) {
    items[i].setMap(null);
  }
  items.length = 0;
}

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


Управление повторным использованием объектов

Вместо удаления и пересоздания объектов иногда применяется паттерн переиспользования:

marker.setPosition(newPosition);
marker.setMap(map);

Если объект уже существует, его можно временно скрывать и возвращать на карту без создания нового экземпляра, что снижает нагрузку на GC и ускоряет обновление интерфейса.