В основе архитектуры библиотеки лежит модель слоёв (layers), где каждый визуальный или функциональный элемент карты представлен отдельным объектом, который можно добавлять на карту или удалять с неё. Карта выступает контейнером, управляющим набором слоёв, а сами слои реализуют единый интерфейс с методами добавления и удаления.
Любой слой в Leaflet реализует базовый контракт: он может быть
подключён к карте через addTo(map) и удалён через
remove() либо через управление картой
map.removeLayer(layer).
Слой добавляется через метод карты:
const map = L.map('map').setView([51.505, -0.09], 13);
const marker = L.marker([51.5, -0.09]);
marker.addTo(map);
Эквивалентная запись через карту:
map.addLayer(marker);
Оба варианта идентичны по результату. Метод addTo(map)
является синтаксическим сахаром, внутри он вызывает
map.addLayer(this).
Удаление выполняется двумя способами:
map.removeLayer(marker);
или через сам слой:
marker.remove();
Обе операции приводят к удалению слоя из внутреннего списка карты и его деактивации на экране.
Карта хранит слои в структуре, разделённой на группы:
Каждый добавленный слой регистрируется внутри карты и получает доступ к жизненному циклу:
onAdd(map) — вызывается при добавленииonRemove(map) — вызывается при удаленииПример внутренней логики:
map.addLayer = function (layer) {
this._layers[L.stamp(layer)] = layer;
layer.onAdd(this);
};
Удаление:
map.removeLayer = function (layer) {
delete this._layers[L.stamp(layer)];
layer.onRemove(this);
};
Маркеры — самый простой тип слоёв:
const marker = L.marker([55.75, 37.61]);
marker.addTo(map);
При добавлении создаётся DOM-элемент, который вставляется в overlayPane карты.
Удаление:
marker.remove();
Тайловые слои представляют собой подложку карты:
const tiles = L.tileLayer('https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png');
tiles.addTo(map);
При добавлении создаётся контейнер, загружаются тайлы, запускается система подгрузки по координатам.
Удаление:
map.removeLayer(tiles);
После удаления тайлы перестают загружаться, DOM очищается.
GeoJSON слой представляет коллекцию геометрий:
const geojson = L.geoJSON(data);
geojson.addTo(map);
При добавлении происходит:
Удаление:
geojson.remove();
Группа слоёв позволяет управлять набором объектов как единым целым:
const group = L.layerGroup();
const marker1 = L.marker([51.5, -0.1]);
const marker2 = L.marker([51.51, -0.12]);
group.addLayer(marker1);
group.addLayer(marker2);
group.addTo(map);
Удаление всей группы:
map.removeLayer(group);
Или:
group.remove();
Особенность: удаление группы автоматически удаляет все вложенные слои с карты.
FeatureGroup расширяет LayerGroup и добавляет событийную модель:
const featureGroup = L.featureGroup([marker1, marker2]).addTo(map);
Дополнительные возможности:
Удаление:
featureGroup.remove();
Для динамического включения и выключения слоёв используется контрол:
const baseMaps = {
"OSM": osmLayer,
"Satellite": satelliteLayer
};
const overlayMaps = {
"Markers": markerGroup,
"Routes": routeLayer
};
L.control.layers(baseMaps, overlayMaps).addTo(map);
Этот механизм автоматически вызывает:
addLayer при включении чекбоксаremoveLayer при выключенииКонтрол работает поверх той же системы
map.addLayer / removeLayer.
Карта позволяет проверить, добавлен ли слой:
map.hasLayer(marker);
Возвращает:
true — слой активенfalse — слой отсутствуетЭто используется при динамическом управлении состоянием интерфейса.
Слои и карта генерируют события при добавлении и удалении.
map.on('layeradd', function (e) {
console.log('Добавлен слой:', e.layer);
});
map.on('layerremove', function (e) {
console.log('Удалён слой:', e.layer);
});
Каждый слой реагирует на жизненный цикл:
const customLayer = L.layerGroup();
customLayer.on('add', function (e) {
console.log('Группа добавлена на карту');
});
customLayer.on('remove', function (e) {
console.log('Группа удалена с карты');
});
Частый сценарий — переключение между наборами данных:
let currentLayer = L.geoJSON(data1).addTo(map);
function switchData(data) {
map.removeLayer(currentLayer);
currentLayer = L.geoJSON(data);
map.addLayer(currentLayer);
}
Здесь важен порядок операций:
При работе с большим количеством объектов используется массив слоёв:
const layers = [];
for (let i = 0; i < 10; i++) {
const marker = L.marker([51.5 + i * 0.01, -0.09]);
layers.push(marker);
marker.addTo(map);
}
Удаление всех слоёв:
layers.forEach(layer => map.removeLayer(layer));
layers.length = 0;
Полная очистка пользовательских слоёв:
map.eachLayer(function (layer) {
if (!layer._url) {
map.removeLayer(layer);
}
});
Здесь используется фильтрация базового тайлового слоя.
Временные объекты часто создаются и удаляются динамически:
function showTemporaryMarker(latlng) {
const marker = L.marker(latlng).addTo(map);
setTimeout(() => {
map.removeLayer(marker);
}, 3000);
}
Такой подход используется для:
Некоторые слои содержат дочерние элементы:
Удаление родителя автоматически вызывает onRemove у всех
потомков:
const group = L.layerGroup([
L.marker([51.5, -0.09]),
L.marker([51.51, -0.1])
]);
group.addTo(map);
group.remove();
Результат: все маркеры также удаляются.
Удаление слоя может требовать перерасчёта карты:
Пример принудительного обновления:
map.invalidateSize();
Используется при изменении контейнера после удаления крупных слоёв.
Порядок добавления влияет на визуальное перекрытие:
map.addLayer(layer1);
map.addLayer(layer2);
layer2 отображается выше.
Можно управлять порядком через panes:
const customPane = map.createPane('customPane');
customPane.style.zIndex = 650;
const marker = L.marker([51.5, -0.09], {
pane: 'customPane'
}).addTo(map);
Удаление слоя также очищает его из соответствующего pane.
Часто слой добавляется только при выполнении условия:
if (!map.hasLayer(marker)) {
map.addLayer(marker);
}
Или безопасное удаление:
if (map.hasLayer(marker)) {
map.removeLayer(marker);
}
Если слой уже добавлен и вызывается addLayer
повторно:
Контрол слоёв синхронизируется автоматически:
const control = L.control.layers(null, {
"Markers": markerLayer
}).addTo(map);
При удалении слоя вручную:
map.removeLayer(markerLayer);
контрол остаётся в UI, но чекбокс может потерять синхронизацию без дополнительного обновления логики.
Система можно представить как поток:
addLayeronAddУдаление:
removeLayeronRemoveПри масштабных проектах используется централизованный менеджер слоёв:
const layerManager = {
activeLayers: [],
add(layer) {
this.activeLayers.push(layer);
layer.addTo(map);
},
remove(layer) {
map.removeLayer(layer);
this.activeLayers = this.activeLayers.filter(l => l !== layer);
}
};
Такой подход упрощает контроль состояния карты при большом количестве динамических объектов.