Визуальное оформление карты в Mapbox GL JS определяется стилем (style), представляющим собой JSON-спецификацию по стандарту Mapbox Style Specification. Стиль описывает источники данных, слои, типы рендеринга, шрифты, спрайты и множество визуальных параметров. Одной из ключевых возможностей является динамическое изменение стиля во время работы приложения без перезагрузки страницы и без пересоздания карты.
Основной метод изменения стиля:
map.setStyle('mapbox://styles/mapbox/streets-v12');
После вызова происходит полная перезагрузка графического состояния карты: очищаются текущие слои, источники и перезапускается процесс загрузки нового style.json.
Важно учитывать, что смена стиля — это не косметическое обновление, а фактически пересборка всей карты.
При вызове setStyle происходит последовательность
внутренних этапов:
styledatastyle.loadКлючевым моментом является то, что любые добавленные вручную слои и источники исчезают после смены стиля.
Для корректной работы после смены стиля используется событие:
map.on('style.load', () => {
// повторное добавление слоев и источников
});
Также часто применяется:
map.on('styledata', () => {
// промежуточное состояние загрузки стиля
});
style.load вызывается один раз после полной загрузки
нового стиля, тогда как styledata может вызываться
многократно в процессе загрузки ресурсов.
После вызова setStyle все следующие элементы
удаляются:
sourceslayersaddImage)Это поведение требует архитектурного подхода к повторной инициализации.
Типовой подход заключается в хранении описания пользовательских слоев и источников:
const customLayers = [
{
id: 'points-layer',
type: 'circle',
source: 'points-source',
paint: {
'circle-radius': 6,
'circle-color': '#ff0000'
}
}
];
const customSources = {
'points-source': {
type: 'geojson',
data: '/data/points.geojson'
}
};
После смены стиля выполняется повторная инициализация:
map.on('style.load', () => {
Object.entries(customSources).forEach(([id, source]) => {
map.addSource(id, source);
});
customLayers.forEach(layer => {
map.addLayer(layer);
});
});
Существует способ частично сохранить данные источников, если новый стиль совместим по структуре:
const currentSources = map.getStyle().sources;
const currentLayers = map.getStyle().layers;
map.setStyle(newStyleUrl);
После загрузки нового стиля выполняется адаптация, используя
сохранённые данные. Однако прямое восстановление невозможно без
повторного addSource.
При использовании кастомных иконок:
map.loadImage('/icon.png', (error, image) => {
if (!error) map.addImage('custom-icon', image);
});
После смены стиля изображения исчезают и требуют повторной загрузки:
map.on('style.load', () => {
map.loadImage('/icon.png', (error, image) => {
if (!error && !map.hasImage('custom-icon')) {
map.addImage('custom-icon', image);
}
});
});
Резкая смена стиля может вызывать визуальные скачки. Для сглаживания применяется промежуточная логика:
Пример:
map.setPaintProperty('water-layer', 'fill-opacity', 0);
map.once('style.load', () => {
map.setPaintProperty('water-layer', 'fill-opacity', 1);
});
Состояние загрузки контролируется через:
if (map.isStyleLoaded()) {
// безопасно работать со слоями
}
Это предотвращает ошибки добавления слоев до завершения загрузки ресурсов.
Типовой сценарий — переключение между темной и светлой темой:
const styles = {
light: 'mapbox://styles/mapbox/light-v11',
dark: 'mapbox://styles/mapbox/dark-v11'
};
function switchStyle(mode) {
map.setStyle(styles[mode]);
}
После смены стиля все визуальные компоненты пересобираются, поэтому логика повторного добавления слоев становится обязательной.
При наличии сложных визуальных схем применяется централизованная функция восстановления:
function restoreMapState() {
addSources();
addLayers();
addControls();
addImages();
}
map.on('style.load', restoreMapState);
Подобный подход упрощает сопровождение при наличии нескольких стилей.
Mapbox GL JS поддерживает выражения для динамического изменения свойств слоёв. При смене стиля:
Пример:
const layer = {
id: 'population',
type: 'fill',
source: 'states',
paint: {
'fill-color': [
'interpolate',
['linear'],
['get', 'pop_density'],
0, '#f2f0f7',
1000, '#cbc9e2',
5000, '#6a51a3'
]
}
};
При частой смене стилей учитываются следующие факторы:
Предварительная инициализация:
const preloadedMap = new mapboxgl.Map({
container: 'hidden',
style: 'mapbox://styles/mapbox/dark-v11'
});
Источники данных делятся на:
При смене стиля:
addSourcemap.addSource('cities', {
type: 'geojson',
data: '/data/cities.geojson'
});
Для координации сложных переходов используется последовательность:
setStylestyle.loadСмена стиля не влияет на:
center)zoom)pitch)bearing)Это позволяет отделять визуальное оформление от географического состояния.
Частые источники проблем:
style.loadКорректная синхронизация выполняется через события загрузки стиля и проверку наличия ресурсов:
if (!map.getSource('points')) {
map.addSource('points', sourceConfig);
}