В интерфейсах на основе картографической библиотеки Leaflet особое значение имеет управление плотностью элементов управления. Карта редко существует в изоляции: поверх неё размещаются слои, переключатели, фильтры, легенды, формы поиска, информационные панели. При ограниченном пространстве экрана требуется механизм переключения между компактным (свёрнутым) и расширенным (развёрнутым) представлением элементов интерфейса.
Свёрнутый вид в Leaflet обычно реализуется через скрытие или минимизацию панели управления, оставляя на карте только компактный элемент — кнопку, иконку или узкую полоску. Развёрнутый вид, напротив, раскрывает полный интерфейс с множеством контролов, списков слоёв или дополнительных настроек. Оба состояния часто управляются через CSS-классы и события DOM, интегрированные в архитектуру Leaflet Control API.
В Leaflet все элементы управления наследуются от базового класса
L.Control. Этот класс определяет механизм добавления
контролов на карту и их позиционирования через опции
position.
Каждый контрол реализует метод:
onAdd(map) — создание DOM-структурыonRemove(map) — очистка при удаленииИменно внутри onAdd формируется логика свёрнутого и
развёрнутого состояния.
Базовая структура:
L.Control.Custom = L.Control.extend({
onAdd: function(map) {
const container = L.DomUtil.create('div', 'custom-control');
return container;
}
});
Свёрнутый вид представляет собой компактную версию интерфейса, которая минимизирует занимаемое пространство карты. Основные характеристики:
В Leaflet свёрнутое состояние чаще всего реализуется через CSS-класс, например:
.custom-control.collapsed {
width: 32px;
height: 32px;
overflow: hidden;
}
DOM при этом остаётся в дереве, но визуально скрывается содержимое.
Развёрнутый вид включает полное отображение функциональности:
Пример CSS:
.custom-control.expanded {
width: 220px;
height: auto;
background: white;
padding: 10px;
}
Развёрнутый вид обычно активируется кликом по кнопке сворачивания/разворачивания.
Переключение между состояниями строится на изменении CSS-класса контейнера.
L.Control.TogglePanel = L.Control.extend({
onAdd: function(map) {
const container = L.DomUtil.create('div', 'toggle-panel collapsed');
const button = L.DomUtil.create('button', 'toggle-button', container);
button.innerHTML = '☰';
const content = L.DomUtil.create('div', 'panel-content', container);
content.innerHTML = `
<div>Слой 1</div>
<div>Слой 2</div>
<div>Слой 3</div>
`;
L.DomEvent.on(button, 'click', function(e) {
L.DomEvent.stopPropagation(e);
L.DomEvent.preventDefault(e);
if (L.DomUtil.hasClass(container, 'collapsed')) {
L.DomUtil.removeClass(container, 'collapsed');
L.DomUtil.addClass(container, 'expanded');
} else {
L.DomUtil.removeClass(container, 'expanded');
L.DomUtil.addClass(container, 'collapsed');
}
});
return container;
}
});
Одним из наиболее распространённых примеров является стандартный
L.control.layers, который уже содержит механизм
свёрнутого/развёрнутого вида.
const baseLayers = {
"OSM": osmLayer,
"Satellite": satelliteLayer
};
const overlays = {
"Дороги": roadsLayer,
"Здания": buildingsLayer
};
L.control.layers(baseLayers, overlays, {
collapsed: true
}).addTo(map);
Параметр collapsed управляет состоянием:
true — панель свёрнута (иконка раскрытия)false — панель всегда развернутаВнутри Leaflet этот механизм реализован через добавление/удаление
CSS-класса leaflet-control-layers-expanded.
Leaflet использует стандартную модель:
.leaflet-control-layers {
background: #fff;
padding: 6px;
}
.leaflet-control-layers-expanded {
width: 200px;
}
Свёрнутый вариант:
Развёрнутый вариант:
Иногда состояние панели связывается с событиями карты, например масштабированием или изменением режима отображения.
map.on('zoomend', function() {
const control = document.querySelector('.toggle-panel');
if (map.getZoom() < 10) {
control.classList.add('collapsed');
control.classList.remove('expanded');
}
});
Такой подход позволяет автоматически изменять интерфейс в зависимости от контекста.
Для улучшения визуального восприятия используется CSS-анимация:
.toggle-panel {
transition: all 0.25s ease;
overflow: hidden;
}
.toggle-panel.collapsed .panel-content {
max-height: 0;
opacity: 0;
}
.toggle-panel.expanded .panel-content {
max-height: 400px;
opacity: 1;
}
Эта модель обеспечивает плавный переход между состояниями без пересоздания DOM.
В архитектуре Leaflet-контролов важно разделять:
Пример выделения состояния:
function setPanelState(container, state) {
container.classList.toggle('collapsed', state === 'collapsed');
container.classList.toggle('expanded', state === 'expanded');
}
Leaflet не ограничивает создание сложных интерфейсов. Свёрнутые и развёрнутые панели часто реализуются как самостоятельные UI-компоненты поверх карты.
Пример структуры:
L.Control.Sidebar = L.Control.extend({
onAdd: function(map) {
const container = L.DomUtil.create('div', 'sidebar collapsed');
const toggle = L.DomUtil.create('div', 'sidebar-toggle', container);
const body = L.DomUtil.create('div', 'sidebar-body', container);
toggle.oncl ick = function() {
container.classList.toggle('collapsed');
container.classList.toggle('expanded');
};
return container;
}
});
В расширенном состоянии интерфейс часто включает динамическое управление слоями:
Пример:
function toggleLayer(layer, enabled) {
if (enabled) {
map.addLayer(layer);
} else {
map.removeLayer(layer);
}
}
Эта логика часто привязывается к чекбоксам внутри развёрнутой панели.
Свёрнутый режим часто используется для оптимизации производительности интерфейса:
Пример отключения:
function collapsePanel(panel) {
panel.classList.add('collapsed');
const items = panel.querySelectorAll('.heavy-item');
items.forEach(el => el.style.display = 'none');
}
Свёрнутый и развёрнутый виды часто зависят от размера экрана:
@media (max-width: 600px) {
.toggle-panel {
width: 32px;
}
.toggle-panel.expanded {
width: 100%;
}
}
На мобильных устройствах свёрнутый вид становится основным состоянием, а развёрнутый — полноэкранным слоем.
При разворачивании панелей важно учитывать слойность интерфейса Leaflet:
Пример:
.toggle-panel {
position: absolute;
z-index: 1000;
}
Развёрнутые панели часто требуют увеличения z-index для
предотвращения перекрытия маркеров или popup-окон.
В более сложных приложениях состояние свёрнутости выносится из DOM:
const panelState = {
layers: 'collapsed'
};
function toggleLayersPanel() {
panelState.layers =
panelState.layers === 'collapsed' ? 'expanded' : 'collapsed';
}
Такой подход облегчает интеграцию с фреймворками (React, Vue, Svelte), даже при использовании Leaflet как низкоуровневого слоя визуализации.
Свёрнутый и развёрнутый виды в Leaflet применяются для управления плотностью информации:
В каждом случае выбор состояния определяется балансом между доступностью функций и визуальной перегрузкой карты.