LayerGroup: базовая группировка

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

LayerGroup реализует интерфейс слоя Leaflet, поэтому может быть добавлен на карту так же, как маркер, тайловый слой или GeoJSON-объект.


Концепция группировки слоёв

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

Ключевая идея:

  • слои добавляются не напрямую на карту
  • слои помещаются в группу
  • группа управляется как единый объект

Такой подход особенно полезен при работе с:

  • наборами маркеров
  • тематическими слоями (например, инфраструктура, транспорт, зоны)
  • динамическими данными, загружаемыми пакетами

Создание LayerGroup

Базовая форма создания группы:

const group = L.layerGroup();

Группа изначально пустая и может принимать слои в момент создания:

const group = L.layerGroup([
  L.marker([51.5, -0.09]),
  L.marker([51.51, -0.1]),
  L.circle([51.49, -0.08], { radius: 200 })
]);

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


Добавление LayerGroup на карту

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

group.addTo(map);

или альтернативно:

map.addLayer(group);

При этом все вложенные элементы становятся видимыми одновременно.


Добавление и удаление слоёв

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

Добавление слоя:

group.addLayer(L.marker([51.52, -0.1]));

Удаление слоя:

group.removeLayer(marker);

Очистка группы:

group.clearLayers();

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


Проверка наличия слоя

Для проверки принадлежности слоя группе используется:

group.hasLayer(marker);

Метод возвращает true, если слой находится внутри группы.


Перебор слоёв группы

Для обхода всех слоёв используется метод eachLayer:

group.eachLayer(function (layer) {
  console.log(layer);
});

Это основной способ выполнения массовых операций:

  • изменение стиля
  • привязка событий
  • фильтрация объектов

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

LayerGroup наследует поведение слоя карты, поэтому:

map.removeLayer(group);

скрывает все вложенные элементы одновременно, а:

map.addLayer(group);

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


Применение LayerGroup как логической категории

LayerGroup часто используется как контейнер тематических данных.

Пример: группа «рестораны»

const restaurants = L.layerGroup();

L.marker([51.5, -0.09]).addTo(restaurants);
L.marker([51.51, -0.1]).addTo(restaurants);
L.marker([51.49, -0.08]).addTo(restaurants);

restaurants.addTo(map);

Аналогично создаются группы:

  • транспорт
  • отели
  • достопримечательности
  • зоны покрытия

Взаимодействие с контролом слоёв

LayerGroup тесно связан с контролом переключения слоёв:

const baseLayers = {};
const overlays = {
  "Рестораны": restaurants
};

L.control.layers(baseLayers, overlays).addTo(map);

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


Отличие LayerGroup от FeatureGroup

Хотя LayerGroup и FeatureGroup внешне похожи, их назначение различается.

LayerGroup:

  • простая группировка слоёв
  • не поддерживает события коллекции
  • минимальная логика

FeatureGroup:

  • расширяет LayerGroup
  • поддерживает события (click, mouseover)
  • позволяет работать с объединёнными геометриями
  • используется для интерактивных объектов

LayerGroup применяется там, где не требуется агрегированная интерактивность.


Вложенные группы

LayerGroup может содержать другие LayerGroup, образуя иерархию:

const groupA = L.layerGroup([
  L.marker([51.5, -0.09])
]);

const groupB = L.layerGroup([
  L.marker([51.51, -0.1])
]);

const mainGroup = L.layerGroup([groupA, groupB]);
mainGroup.addTo(map);

Это позволяет строить сложные структуры слоёв с многоуровневым управлением.


Работа с динамическими данными

LayerGroup особенно полезен при загрузке данных с сервера.

Типичный сценарий:

  1. создаётся пустая группа
  2. выполняется запрос к API
  3. данные преобразуются в слои
  4. слои добавляются в группу
const dynamicGroup = L.layerGroup().addTo(map);

fetch('/api/points')
  .then(res => res.json())
  .then(data => {
    data.forEach(item => {
      L.marker([item.lat, item.lng]).addTo(dynamicGroup);
    });
  });

Обновление данных выполняется через очистку и повторное заполнение:

dynamicGroup.clearLayers();

Массовые операции над слоями

LayerGroup позволяет выполнять операции над всеми элементами одновременно:

Изменение стиля

group.eachLayer(layer => {
  if (layer.setStyle) {
    layer.setStyle({ color: 'red' });
  }
});

Привязка событий

group.eachLayer(layer => {
  layer.on('click', () => {
    console.log('click');
  });
});

Фильтрация

group.eachLayer(layer => {
  if (layer.feature && layer.feature.properties.hidden) {
    group.removeLayer(layer);
  }
});

Производительность LayerGroup

LayerGroup не создаёт отдельного рендеринга. Он лишь управляет добавлением и удалением DOM-слоёв Leaflet.

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

  • количества вложенных объектов
  • частоты обновления группы
  • сложности геометрий

Оптимизация достигается за счёт:

  • пакетного добавления слоёв
  • использования clearLayers вместо поэлементного удаления
  • минимизации перерисовок карты

Поведение при зуме и перерисовке

LayerGroup не влияет на поведение карты при зуме или панорамировании. Все вложенные слои ведут себя как самостоятельные объекты Leaflet:

  • маркеры сохраняют позицию
  • полигоны масштабируются
  • тайлы перерисовываются независимо

Группа лишь контролирует их присутствие на карте.


Использование для переключения режимов отображения

LayerGroup часто применяется для реализации режимов отображения:

const trafficLayer = L.layerGroup();
const satelliteLayer = L.layerGroup();

map.addLayer(trafficLayer);

Переключение осуществляется через удаление и добавление групп:

map.removeLayer(trafficLayer);
map.addLayer(satelliteLayer);

Комбинирование с GeoJSON

GeoJSON-слои легко интегрируются в LayerGroup:

const geoGroup = L.layerGroup();

L.geoJSON(data).addTo(geoGroup);
geoGroup.addTo(map);

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


Очистка и повторное использование группы

Один и тот же LayerGroup может использоваться многократно:

group.clearLayers();

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

Такой подход характерен для интерфейсов, где данные постоянно обновляются, но структура группы сохраняется.


Роль LayerGroup в архитектуре карты

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

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

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