В процессе работы с картами часто возникает ситуация, когда часть слоев временно не отображается пользователю. Причины могут быть различными:
Несмотря на отсутствие визуального отображения, слой продолжает существовать внутри стиля карты. Если управление видимостью реализовано неэффективно, скрытые слои могут участвовать в обработке данных, занимать память и усложнять поддержку проекта.
Под отключением невидимых слоев обычно понимается перевод слоя в состояние, при котором он полностью исключается из процесса визуализации.
Основным механизмом управления отображением слоя является свойство
visibility, расположенное в секции layout.
Допустимые значения:
visible
none
Пример изменения видимости слоя:
map.setLayoutProperty(
'roads-layer',
'visibility',
'none'
);
Для повторного отображения:
map.setLayoutProperty(
'roads-layer',
'visibility',
'visible'
);
Внутри стиля Mapbox слой будет выглядеть следующим образом:
{
id: 'roads-layer',
type: 'line',
source: 'roads',
layout: {
visibility: 'visible'
}
}
После отключения:
{
id: 'roads-layer',
type: 'line',
source: 'roads',
layout: {
visibility: 'none'
}
}
Когда значение равно none, слой не участвует в отрисовке
карты.
Перед изменением настроек полезно определить текущее состояние слоя.
Получение свойства:
const visibility = map.getLayoutProperty(
'roads-layer',
'visibility'
);
console.log(visibility);
Результат:
visible
или
none
На основе полученного значения можно реализовать переключатель:
const visibility = map.getLayoutProperty(
'roads-layer',
'visibility'
);
if (visibility === 'visible') {
map.setLayoutProperty(
'roads-layer',
'visibility',
'none'
);
} else {
map.setLayoutProperty(
'roads-layer',
'visibility',
'visible'
);
}
Типичный сценарий — предоставление пользователю возможности скрывать и показывать слои.
HTML:
<button id="toggle-roads">
Переключить дороги
</button>
Jav * aScript:
document
.getElementById('toggle-roads')
.addEventListener('click', () => {
const visibility =
map.getLayoutProperty(
'roads-layer',
'visibility'
);
map.setLayoutProperty(
'roads-layer',
'visibility',
visibility === 'visible'
? 'none'
: 'visible'
);
});
Такой подход широко используется при создании панелей управления картой.
Во многих стилях один логический набор данных представлен несколькими слоями.
Например:
buildings-fill
buildings-outline
buildings-labels
Для скрытия всего блока объектов можно использовать цикл:
const buildingLayers = [
'buildings-fill',
'buildings-outline',
'buildings-labels'
];
buildingLayers.forEach(layerId => {
map.setLayoutProperty(
layerId,
'visibility',
'none'
);
});
Обратное включение:
buildingLayers.forEach(layerId => {
map.setLayoutProperty(
layerId,
'visibility',
'visible'
);
});
Такой способ позволяет централизованно управлять тематическими группами слоев.
В крупных приложениях количество слоев может исчисляться десятками и сотнями.
Для удобства создается объект конфигурации:
const layers = {
roads: [
'roads-main',
'roads-secondary'
],
buildings: [
'building-fill',
'building-outline'
],
water: [
'water-fill',
'water-outline'
]
};
Универсальная функция отключения:
function hideGroup(groupName) {
layers[groupName].forEach(layerId => {
map.setLayoutProperty(
layerId,
'visibility',
'none'
);
});
}
Использование:
hideGroup('buildings');
Подобная организация кода значительно упрощает сопровождение проекта.
Иногда слой должен отображаться только на определенных масштабах.
Для этого используются свойства:
minzoom
maxzoom
Пример:
map.addLayer({
id: 'city-labels',
type: 'symbol',
source: 'cities',
minzoom: 8,
maxzoom: 14
});
Поведение:
| Масштаб | Отображение |
|---|---|
| 0–7 | Скрыт |
| 8–13 | Видим |
| 14+ | Скрыт |
В таких случаях ручное переключение видимости не требуется.
Иногда необходимо не отключить слой полностью, а временно убрать все объекты.
Для этого можно использовать фильтр, который не соответствует ни одному объекту.
Пример:
map.setFilter(
'roads-layer',
['==', 'id', -1]
);
Поскольку объекта с таким значением нет, слой фактически становится пустым.
Возврат фильтра:
map.setFilter(
'roads-layer',
null
);
Однако данный подход отличается от установки
visibility: none.
Слой продолжает существовать и участвовать в обработке данных.
Распространенная ошибка — использование прозрачности вместо отключения слоя.
Например:
map.setPaintProperty(
'roads-layer',
'line-opacity',
0
);
Визуально слой исчезнет.
Но движок продолжит:
Поэтому прозрачность не является полноценным отключением.
Для скрытия слоя рекомендуется:
map.setLayoutProperty(
'roads-layer',
'visibility',
'none'
);
В некоторых случаях слой больше не понадобится в текущей сессии.
Тогда его можно удалить.
Сначала удаляется слой:
map.removeLayer('roads-layer');
После этого при необходимости удаляется источник данных:
map.removeSource('roads');
Сравнение подходов:
| Метод | Можно быстро вернуть | Освобождает ресурсы |
|---|---|---|
| visibility: none | Да | Частично |
| removeLayer() | Нет | Да |
| removeLayer() + removeSource() | Нет | Максимально |
Удаление подходит для редко используемых данных большого объема.
При динамическом управлении стилями слой может отсутствовать.
Без проверки возникнет ошибка:
map.setLayoutProperty(
'roads-layer',
'visibility',
'none'
);
Безопасный вариант:
if (map.getLayer('roads-layer')) {
map.setLayoutProperty(
'roads-layer',
'visibility',
'none'
);
}
Подобная проверка особенно важна при переключении стилей карты.
Иногда необходимо временно очистить карту от пользовательских данных.
Пример:
const style = map.getStyle();
style.layers.forEach(layer => {
if (
layer.id.startsWith('custom-')
) {
map.setLayoutProperty(
layer.id,
'visibility',
'none'
);
}
});
Такой подход эффективен при работе с большим количеством динамически создаваемых слоев.
Часто состояние слоя зависит от глобального состояния интерфейса.
Например:
window.addEventListener(
'hideAnalysis',
() => {
analysisLayers.forEach(id => {
map.setLayoutProperty(
id,
'visibility',
'none'
);
});
}
);
Для повторного отображения:
window.addEventListener(
'showAnalysis',
() => {
analysisLayers.forEach(id => {
map.setLayoutProperty(
id,
'visibility',
'visible'
);
});
}
);
Подобный механизм часто используется в приложениях с архитектурой на основе событий.
При работе со сложными картографическими приложениями необходимо учитывать следующие рекомендации:
Отключать неиспользуемые слои через
visibility: none.
map.setLayoutProperty(
layerId,
'visibility',
'none'
);
Не заменять отключение прозрачностью.
Плохо:
line-opacity: 0
Хорошо:
visibility: none
Группировать слои по функциональным категориям.
Пример:
transportLayers
analysisLayers
buildingLayers
weatherLayers
Удалять тяжелые временные слои после завершения работы.
map.removeLayer(layerId);
map.removeSource(sourceId);
Проверять существование слоя перед изменением его свойств.
if (map.getLayer(layerId)) {
// изменение настроек
}
Использовать minzoom и maxzoom для
автоматического скрытия слоев на неподходящих масштабах.
Такой подход позволяет сохранять высокую производительность даже в проектах с большим количеством источников данных и сложной структурой стилей.