Свойство visibility определяет, отображается ли слой на карте. Оно относится к группе layout properties и является одним из наиболее часто используемых параметров при создании интерактивных карт. Управление видимостью позволяет динамически показывать и скрывать слои без их удаления из карты и без повторной загрузки данных.
В Mapbox GL JS значение свойства задаётся через параметр:
layout: {
visibility: 'visible'
}
или изменяется после создания слоя с помощью метода:
map.setLayoutProperty(layerId, 'visibility', 'none');
Поддерживаются только два значения:
| Значение | Описание |
|---|---|
visible |
Слой отображается |
none |
Слой скрыт |
Каждый слой карты проходит этапы:
Когда свойство принимает значение:
visibility: 'visible'
слой участвует в процессе отрисовки.
Когда используется:
visibility: 'none'
слой остаётся зарегистрированным в стиле карты, но его объекты не отображаются.
Важно понимать различие между скрытием слоя и его удалением:
map.removeLayer('roads');
Удаление уничтожает слой полностью.
map.setLayoutProperty('roads', 'visibility', 'none');
Скрытие лишь отключает отображение.
Данные при этом продолжают существовать внутри карты.
По умолчанию большинство слоёв являются видимыми.
map.addLayer({
id: 'cities',
type: 'circle',
source: 'cities-source',
paint: {
'circle-radius': 6,
'circle-color': '#ff0000'
},
layout: {
visibility: 'visible'
}
});
Слой может быть добавлен в скрытом состоянии.
map.addLayer({
id: 'cities',
type: 'circle',
source: 'cities-source',
paint: {
'circle-radius': 6,
'circle-color': '#ff0000'
},
layout: {
visibility: 'none'
}
});
После загрузки карты такой слой не будет отображаться до изменения свойства.
Наиболее распространённый сценарий — переключение отображения во время работы приложения.
map.setLayoutProperty(
'cities',
'visibility',
'none'
);
map.setLayoutProperty(
'cities',
'visibility',
'visible'
);
Для определения текущей видимости используется метод:
map.getLayoutProperty(
'cities',
'visibility'
);
Результат:
'visible'
или
'none'
Пример:
const visibility =
map.getLayoutProperty(
'cities',
'visibility'
);
console.log(visibility);
Один из наиболее популярных сценариев — кнопка включения и отключения слоя.
button.addEventListener('click', () => {
const visibility =
map.getLayoutProperty(
'cities',
'visibility'
);
if (visibility === 'visible') {
map.setLayoutProperty(
'cities',
'visibility',
'none'
);
} else {
map.setLayoutProperty(
'cities',
'visibility',
'visible'
);
}
});
Такой подход используется практически во всех интерфейсах управления слоями.
Часто карта содержит множество тематических слоёв:
Каждый слой может включаться и выключаться независимо.
const layers = [
'roads',
'buildings',
'water'
];
layers.forEach(layerId => {
const checkbox =
document.createElement('input');
checkbox.type = 'checkbox';
checkbox.checked = true;
checkbox.addEventListener('change', () => {
map.setLayoutProperty(
layerId,
'visibility',
checkbox.checked
? 'visible'
: 'none'
);
});
});
Подобная структура лежит в основе большинства GIS-интерфейсов.
Скрытие слоя значительно эффективнее его постоянного удаления и повторного создания.
Нежелательный вариант:
map.removeLayer('roads');
map.addLayer({
id: 'roads',
...
});
Предпочтительный вариант:
map.setLayoutProperty(
'roads',
'visibility',
'none'
);
Причины:
Для временного отключения отображения всегда рекомендуется
использовать visibility.
Скрытие слоя не влияет на источник данных.
Например:
map.addSource('cities', {
type: 'geojson',
data: citiesData
});
Если затем скрыть слой:
map.setLayoutProperty(
'cities-layer',
'visibility',
'none'
);
источник cities продолжит существовать.
Его данные остаются доступными:
map.getSource('cities');
Это особенно важно для приложений, где несколько слоёв используют один и тот же source.
Скрытие слоя отличается от фильтрации объектов.
map.setLayoutProperty(
'cities',
'visibility',
'none'
);
На карте не отображается ничего.
map.setFilter('cities', [
'==',
'country',
'France'
]);
Слой остаётся активным, но отображает только подходящие объекты.
Сравнение:
| Механизм | Результат |
|---|---|
visibility |
Скрывается весь слой |
filter |
Скрываются отдельные объекты |
removeLayer |
Слой удаляется полностью |
Видимость слоя можно комбинировать с ограничениями масштаба.
map.addLayer({
id: 'buildings',
type: 'fill',
source: 'buildings',
minzoom: 15,
layout: {
visibility: 'visible'
}
});
Слой будет отображаться:
visibility равно
visible.Если установить:
map.setLayoutProperty(
'buildings',
'visibility',
'none'
);
то слой не будет показываться даже при подходящем масштабе.
Иногда необходимо скрыть сразу несколько слоёв.
const thematicLayers = [
'roads',
'bridges',
'tunnels',
'railways'
];
thematicLayers.forEach(layerId => {
map.setLayoutProperty(
layerId,
'visibility',
'none'
);
});
Включение выполняется аналогично:
thematicLayers.forEach(layerId => {
map.setLayoutProperty(
layerId,
'visibility',
'visible'
);
});
Часто карта поддерживает несколько режимов отображения.
Например:
Для транспортного режима:
map.setLayoutProperty(
'roads',
'visibility',
'visible'
);
map.setLayoutProperty(
'railways',
'visibility',
'visible'
);
map.setLayoutProperty(
'tourist-routes',
'visibility',
'none'
);
Для туристического режима:
map.setLayoutProperty(
'roads',
'visibility',
'none'
);
map.setLayoutProperty(
'railways',
'visibility',
'none'
);
map.setLayoutProperty(
'tourist-routes',
'visibility',
'visible'
);
Такой механизм лежит в основе переключения тематических представлений карты.
Попытка изменить несуществующий слой вызывает ошибку.
Надёжный вариант:
if (map.getLayer('cities')) {
map.setLayoutProperty(
'cities',
'visibility',
'none'
);
}
Подобная проверка особенно полезна при работе с динамически создаваемыми слоями.
Свойство часто используется совместно с пользовательскими событиями.
map.on('zoom', () => {
if (map.getZoom() > 12) {
map.setLayoutProperty(
'cities',
'visibility',
'visible'
);
} else {
map.setLayoutProperty(
'cities',
'visibility',
'none'
);
}
});
select.addEventListener(
'change',
event => {
map.setLayoutProperty(
'roads',
'visibility',
event.target.value === 'roads'
? 'visible'
: 'none'
);
}
);
В Mapbox GL JS отсутствует понятие группы слоёв на уровне API. Обычно группировка реализуется программно.
const weatherLayers = [
'temperature',
'wind',
'precipitation'
];
Скрытие всей группы:
weatherLayers.forEach(layer => {
map.setLayoutProperty(
layer,
'visibility',
'none'
);
});
Показ группы:
weatherLayers.forEach(layer => {
map.setLayoutProperty(
layer,
'visibility',
'visible'
);
});
Неверно:
paint: {
visibility: 'none'
}
Свойство не относится к секции paint.
Правильно:
layout: {
visibility: 'none'
}
Неверно:
visibility: false
или
visibility: true
Mapbox GL JS ожидает строковые значения:
visibility: 'none'
или
visibility: 'visible'
Неверно:
map.setLayoutProperty(
'unknown-layer',
'visibility',
'none'
);
Следует предварительно проверить наличие слоя:
if (map.getLayer('unknown-layer')) {
// изменение свойства
}
Свойство visibility активно используется для решения следующих задач:
Благодаря простоте и высокой производительности свойство
visibility является основным механизмом управления
отображением слоёв в Mapbox GL JS и используется практически в каждом
сложном картографическом приложении.