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

Удаление маркеров в Leaflet осуществляется через работу с объектами слоёв (layer), поскольку каждый маркер представляет собой слой, добавленный на карту. Архитектура библиотеки предполагает, что любые визуальные элементы — маркеры, поли-линии, полигоны — управляются через единый механизм добавления и удаления слоёв.

Каждый маркер, созданный через L.marker, может быть удалён напрямую через объект карты. Основной способ — использование метода удаления слоя:

const marker = L.marker([51.505, -0.09]).addTo(map);

map.removeLayer(marker);

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

Альтернативный вариант — использование метода самого маркера:

const marker = L.marker([51.505, -0.09]).addTo(map);

marker.remove();

Этот метод является обёрткой над удалением слоя с карты и выполняет ту же функцию, но без необходимости явно обращаться к объекту карты.

Также существует вариант:

marker.removeFrom(map);

Этот вызов эквивалентен map.removeLayer(marker) и используется, когда необходимо явно указать карту, с которой происходит удаление.


Удаление маркеров через группы слоёв

При работе с большим количеством маркеров используется группировка через L.layerGroup или L.featureGroup. Это позволяет управлять наборами объектов как единым целым.

const group = L.layerGroup().addTo(map);

const marker1 = L.marker([51.5, -0.1]).addTo(group);
const marker2 = L.marker([51.51, -0.11]).addTo(group);

Удаление всех маркеров группы выполняется одним вызовом:

group.clearLayers();

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

Разница между layerGroup и featureGroup заключается в дополнительной поддержке событий и вычисляемых границ (getBounds), но механизм удаления слоёв идентичен.


Удаление множества маркеров по условию

При хранении ссылок на маркеры в массиве можно выполнять фильтрацию и удаление выборочно:

const markers = [];

markers.push(L.marker([51.5, -0.1]).addTo(map));
markers.push(L.marker([51.51, -0.11]).addTo(map));
markers.push(L.marker([51.49, -0.08]).addTo(map));

markers.forEach(marker => {
  if (marker.getLatLng().lat > 51.5) {
    map.removeLayer(marker);
  }
});

После удаления ссылки на маркер в массиве остаются, поэтому для корректного управления состоянием структуры данных обычно выполняется синхронизация:

for (let i = markers.length - 1; i >= 0; i--) {
  if (markers[i].getLatLng().lat > 51.5) {
    map.removeLayer(markers[i]);
    markers.splice(i, 1);
  }
}

Удаление маркеров по пользовательскому идентификатору

Leaflet не накладывает ограничений на структуру объектов, поэтому каждому маркеру можно назначать произвольные свойства:

const marker = L.marker([51.5, -0.1]);
marker.id = "user_1";
marker.addTo(map);

Удаление по идентификатору реализуется через поиск:

function removeMarkerById(id, markers, map) {
  const index = markers.findIndex(m => m.id === id);
  if (index !== -1) {
    map.removeLayer(markers[index]);
    markers.splice(index, 1);
  }
}

Такой подход применяется при построении интерактивных систем, где маркеры связаны с внешними данными.


Особенности удаления и жизненный цикл объекта

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

const marker = L.marker([51.5, -0.1]).addTo(map);

map.removeLayer(marker);
marker.addTo(map);

Leaflet при удалении выполняет следующие действия:

  • удаляет DOM-элементы маркера;
  • отключает обработчики событий;
  • исключает слой из внутреннего дерева карты;
  • обновляет состояние рендера.

Однако ссылки в коде не очищаются автоматически, поэтому управление памятью остаётся на стороне разработчика.


Удаление через события и взаимодействия

Маркеры часто удаляются в ответ на пользовательские действия:

const marker = L.marker([51.5, -0.1]).addTo(map);

marker.on('click', () => {
  map.removeLayer(marker);
});

Или с использованием внешних событий:

document.getElementById('delete').addEventListener('click', () => {
  map.removeLayer(marker);
});

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

marker.on('remove', () => {
  console.log('Маркер удалён с карты');
});

Массовое удаление маркеров без групп

При отсутствии групп слоёв применяется обход всех слоёв карты:

map.eachLayer(layer => {
  if (layer instanceof L.Marker) {
    map.removeLayer(layer);
  }
});

Такой подход полезен при очистке карты от всех маркеров, но требует осторожности, если на карте присутствуют другие типы слоёв (тайлы, полигоны).


Удаление и производительность

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

  • использовать LayerGroup и clearLayers;
  • минимизировать количество отдельных вызовов removeLayer;
  • группировать операции удаления.
map.removeLayer(group);

Удаление группы одним вызовом снижает количество перерасчётов и DOM-операций.


Типичные ошибки при удалении

Часто встречается попытка удалить маркер, который не добавлен на карту:

const marker = L.marker([51.5, -0.1]);
map.removeLayer(marker); // не имеет эффекта

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

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


Очистка FeatureGroup

При использовании L.featureGroup доступно дополнительное управление:

const group = L.featureGroup().addTo(map);

group.addLayer(L.marker([51.5, -0.1]));
group.addLayer(L.marker([51.51, -0.11]));

group.clearLayers();

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


Повторное использование удалённых маркеров

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

map.removeLayer(marker);

setTimeout(() => {
  marker.addTo(map);
}, 1000);

Это позволяет реализовывать эффекты временного скрытия без потери состояния объекта.