Mapbox GL JS предоставляет механизм runtime styling — динамического изменения визуального представления карты без пересоздания стиля и перезагрузки источников данных. Этот подход опирается на концепцию декларативного описания карты через стиль (style specification) и последующую модификацию отдельных его частей в реальном времени.
В основе runtime styling лежит разделение карты на несколько независимых слоёв абстракции:
Runtime styling работает поверх уже загруженного стиля и позволяет изменять любые его части через API Mapbox GL JS без полной реконфигурации карты.
Метод setStyle полностью заменяет текущий стиль
новым:
map.setStyle('mapbox://styles/mapbox/dark-v11');
Особенности:
При смене стиля важно учитывать событие загрузки:
map.on('style.load', () => {
map.addLayer(customLayer);
});
map.addLayer({
id: 'roads-highlight',
type: 'line',
source: 'composite',
'source-layer': 'road',
paint: {
'line-color': '#ff0000',
'line-width': 2
}
});
Добавление слоя происходит поверх существующего стиля без его пересоздания.
map.removeLayer('roads-highlight');
Удаление слоя мгновенно отражается на карте, не затрагивая источники данных.
map.moveLayer('roads-highlight', 'waterway-label');
Это позволяет управлять порядком отрисовки без пересборки стиля.
Runtime styling наиболее часто используется для изменения визуальных свойств слоёв.
map.setPaintProperty('roads-highlight', 'line-color', '#00ff00');
map.setPaintProperty('roads-highlight', 'line-width', 4);
Paint properties отвечают за визуальные характеристики:
map.setLayoutProperty('road-label', 'visibility', 'none');
Layout properties управляют структурой слоя:
Метод setFilter позволяет изменять отображаемые объекты
без изменения источника.
map.setFilter('roads-highlight', [
'==',
['get', 'class'],
'primary'
]);
Фильтры используют expression syntax Mapbox GL JS:
Пример сложного фильтра:
map.setFilter('roads-highlight', [
'all',
['>=', ['get', 'length'], 100],
['==', ['get', 'class'], 'secondary']
]);
Expressions позволяют вычислять стили на основе данных.
map.setPaintProperty('population', 'fill-color', [
'interpolate',
['linear'],
['get', 'pop_density'],
0, '#2DC4B2',
1000, '#3BB3C3',
5000, '#F1F075',
10000, '#F28CB1'
]);
map.setPaintProperty('buildings', 'fill-opacity', [
'case',
['==', ['get', 'type'], 'residential'],
1,
0.3
]);
Expressions позволяют полностью уйти от ручного пересчёта стилей в JavaScript и делегировать вычисления движку рендеринга.
Feature State используется для изменения внешнего вида отдельных объектов без модификации источника данных.
map.setFeatureState(
{
source: 'buildings',
id: 123
},
{
selected: true
}
);
map.setPaintProperty('buildings', 'fill-color', [
'case',
['boolean', ['feature-state', 'selected'], false],
'#ff0000',
'#0080ff'
]);
Особенности Feature State:
map.getSource('points').setData(newGeojson);
Это основной механизм обновления динамических данных:
Runtime styling часто комбинируется с логикой отображения слоёв:
const isDark = true;
map.setPaintProperty(
'water',
'fill-color',
isDark ? '#001f3f' : '#00bfff'
);
Однако более эффективный подход — выражения:
map.setPaintProperty('water', 'fill-color', [
'match',
['get', 'theme'],
'dark', '#001f3f',
'light', '#00bfff',
'#000000'
]);
Mapbox GL JS не предоставляет классической анимации слоёв, но runtime styling позволяет имитировать её.
map.setPaintProperty('heat', 'circle-radius', [
'interpolate',
['linear'],
['zoom'],
0, 2,
10, 10
]);
map.setPaintProperty('heat', 'circle-color', [
'interpolate',
['linear'],
['get', 'value'],
0, '#2DC4B2',
100, '#F28CB1'
]);
Несмотря на гибкость, существуют ограничения:
setPaintProperty могут вызывать
перерасчёт рендераsetStyle полностью сбрасывает состояние картыmap.batch(() => {
map.setPaintProperty('roads', 'line-color', '#ff0000');
map.setLayoutProperty('labels', 'visibility', 'none');
});
(в реальных реализациях используется минимизация количества вызовов API)
Рекомендуется:
Runtime styling сохраняет декларативную природу Mapbox GL JS:
Это делает систему предсказуемой, масштабируемой и пригодной для сложных визуализаций данных в браузере.