В Leaflet работа с визуальными элементами карты строится вокруг концепции слоёв. Каждый объект — тайлы, маркеры, векторные фигуры, GeoJSON-данные — представляет собой отдельный слой, который может быть добавлен на карту, удалён или изменён.
При усложнении интерфейса возникает необходимость объединять слои в логические группы. Это позволяет управлять множеством объектов как единым целым: включать/выключать наборы данных, изменять порядок отображения, применять операции к группе сразу, а не к каждому элементу отдельно.
Основные механизмы группировки:
LayerGroup — базовая группа слоёвFeatureGroup — расширенная группа с событийной
модельюControl.Layers — UI-компонент управления группами
слоёвL.LayerGroup представляет собой контейнер, который
хранит произвольное количество слоёв и позволяет управлять ими как
единым объектом.
const markers = L.layerGroup();
const marker1 = L.marker([51.5, -0.09]);
const marker2 = L.marker([51.51, -0.1]);
const marker3 = L.marker([51.49, -0.08]);
markers.addLayer(marker1);
markers.addLayer(marker2);
markers.addLayer(marker3);
markers.addTo(map);
LayerGroup не накладывает ограничений на типы слоёв. В одной группе могут находиться:
L.marker)L.polyline)L.polygon)L.circle)group.addLayer(layer);
group.removeLayer(layer);
group.clearLayers();
Метод полностью удаляет все слои из группы, но не уничтожает сам объект группы.
group.eachLayer(function (layer) {
console.log(layer);
});
Каждый слой передаётся в callback-функцию, что позволяет выполнять массовые операции:
LayerGroup используется для:
Пример логической группировки:
const restaurants = L.layerGroup();
const parks = L.layerGroup();
const transport = L.layerGroup();
L.FeatureGroup расширяет LayerGroup, добавляя поддержку
событий и взаимодействия.
Ключевая особенность — группа становится единым интерактивным объектом.
const editableItems = L.featureGroup();
FeatureGroup:
События пробрасываются от внутренних слоёв:
editableItems.on('click', function (e) {
console.log('Клик по любому элементу группы', e.layer);
});
Это позволяет избегать навешивания обработчиков на каждый объект отдельно.
FeatureGroup умеет вычислять bounding box всех вложенных элементов:
const bounds = editableItems.getBounds();
map.fitBounds(bounds);
Это особенно полезно при:
L.control.layers предоставляет интерфейс переключения
между группами слоёв.
const baseMaps = {
"Карта": osm,
"Спутник": satellite
};
const overlayMaps = {
"Рестораны": restaurants,
"Парки": parks
};
L.control.layers(baseMaps, overlayMaps).addTo(map);
Overlay-группы позволяют:
Пример поведения:
Хотя Leaflet не предоставляет формальной древовидной структуры групп, LayerGroup может содержать другие LayerGroup или FeatureGroup.
const cities = L.layerGroup();
const moscowMarkers = L.layerGroup();
const parisMarkers = L.layerGroup();
cities.addLayer(moscowMarkers);
cities.addLayer(parisMarkers);
Такой подход создаёт многоуровневую структуру логики:
страны
города
При группировке слоёв важно учитывать порядок отрисовки.
marker.setZIndexOffset(1000);
Группа наследует поведение вложенных слоёв, но не имеет собственного z-index как контейнер. Порядок определяется:
if (type === 'restaurant') {
restaurants.addLayer(marker);
}
oldGroup.removeLayer(marker);
newGroup.addLayer(marker);
Это позволяет реализовать:
При работе с динамическими данными часто используется полная пересборка:
function rebuildGroup(data) {
group.clearLayers();
data.forEach(item => {
const marker = L.marker(item.coords);
group.addLayer(marker);
});
}
Такой подход упрощает синхронизацию с сервером.
GeoJSON-слои особенно часто группируются.
const geoLayer = L.geoJSON(data);
const group = L.layerGroup([geoLayer]);
Или динамически:
const group = L.featureGroup();
L.geoJSON(data, {
onEachFeature: function (feature, layer) {
group.addLayer(layer);
}
});
Слои внутри группы продолжают генерировать события:
clickmouseovermouseoutdragstartdragendFeatureGroup агрегирует эти события:
group.on('mouseover', function (e) {
e.layer.setStyle({ color: 'red' });
});
При большом количестве объектов группировка влияет на производительность:
addLayer в
циклеclearLayers() вместо удаления по одному
элементуПример оптимизированной загрузки:
map.off();
group.clearLayers();
batch.forEach(item => {
group.addLayer(L.marker(item.coords));
});
map.on();
Хотя группы можно добавлять и удалять с карты, часто используется явное управление:
map.addLayer(group);
map.removeLayer(group);
Вместо управления отдельными слоями используется переключение целых наборов данных.
function filter(category) {
group.clearLayers();
data
.filter(item => item.category === category)
.forEach(item => {
group.addLayer(L.marker(item.coords));
});
}
checkbox.oncha nge = function () {
if (this.checked) {
map.addLayer(restaurants);
} else {
map.removeLayer(restaurants);
}
};
Группы слоёв становятся основой архитектуры карты:
Типичная структура:
const layers = {
traffic: L.layerGroup(),
infrastructure: L.layerGroup(),
analytics: L.featureGroup()
};
Чем больше объём данных, тем важнее структурирование:
Группы становятся аналогом контейнеров состояния для карты, упрощая управление сложными сценами и многослойными визуализациями.