Визуальное оформление слоёв в Mapbox GL JS строится на модели декларативных стилей, где внешний вид объектов карты описывается через свойства слоя. Ключевым механизмом выступает data-driven styling — привязка визуальных параметров к данным источника и масштабу карты, что позволяет формировать динамическую картографическую визуализацию без ручного обновления стилей.
Стили слоя делятся на две фундаментальные группы:
Data-driven подход применяется преимущественно к paint-свойствам, а также частично к layout-параметрам, когда требуется динамическое управление отображением.
map.addLayer({
id: 'cities',
type: 'circle',
source: 'cities-source',
paint: {
'circle-radius': 6,
'circle-color': '#3b82f6'
}
});
Даже базовая конфигурация уже задаёт точку входа для последующего связывания с данными.
Основой data-driven styling выступают выражения Mapbox Style Specification. Они позволяют вычислять значения свойств на основе входных данных.
Основные типы выражений:
Данные из GeoJSON или векторных тайлов доступны через свойства feature:
'circle-color': ['get', 'category']
В данном случае цвет круга зависит от значения свойства
category в каждом объекте.
Интерполяция применяется для плавного изменения визуальных параметров в зависимости от числового атрибута.
'circle-radius': [
'interpolate',
['linear'],
['get', 'population'],
1000, 4,
100000, 10,
1000000, 20
]
Функция задаёт зависимость радиуса круга от численности населения, обеспечивая непрерывное масштабирование символов.
step позволяет разделять диапазон значений на интервалы:
'circle-color': [
'step',
['get', 'density'],
'#fee5d9',
50, '#fcae91',
100, '#fb6a4a',
200, '#cb181d'
]
Каждый диапазон плотности получает фиксированный цвет, формируя тематическую карту классификации.
match используется для дискретных значений, когда атрибут принимает ограниченное число категорий.
'circle-color': [
'match',
['get', 'type'],
'capital', '#e11d48',
'city', '#2563eb',
'town', '#10b981',
'#9ca3af'
]
Последнее значение выступает значением по умолчанию.
case позволяет задавать последовательность условий:
'circle-opacity': [
'case',
['>', ['get', 'importance'], 80],
1,
['>', ['get', 'importance'], 50],
0.6,
0.3
]
Каждое условие проверяется последовательно, пока не будет найдено истинное.
Zoom-aware styling позволяет изменять внешний вид в зависимости от уровня приближения.
'circle-radius': [
'interpolate',
['linear'],
['zoom'],
5, 2,
10, 6,
15, 18
]
Такой подход применяется для регулировки читаемости объектов при разных масштабах.
feature-state обеспечивает динамическое обновление стилей без изменения исходных данных источника. Это критично для интерактивных сценариев.
map.setFeatureState(
{ source: 'cities', id: 123 },
{ selected: true }
);
Стиль слоя может реагировать на состояние:
'circle-color': [
'case',
['boolean', ['feature-state', 'selected'], false],
'#f59e0b',
'#3b82f6'
]
Такой механизм отделяет данные от UI-состояния, снижая необходимость перерендера источника.
Выражения могут вкладываться друг в друга, формируя сложную логику визуализации:
'circle-radius': [
'interpolate',
['linear'],
['zoom'],
5,
['+', 2, ['/', ['get', 'value'], 50]],
10,
['+', 6, ['/', ['get', 'value'], 20]]
]
Композиция арифметических и логических операций позволяет строить адаптивные стили высокой сложности.
Data-driven styling поддерживает использование нескольких полей одновременно:
'circle-color': [
'rgb',
['get', 'r'],
['get', 'g'],
['get', 'b']
]
Цвет формируется непосредственно из данных, что исключает необходимость предрасчёта значений.
Источники данных в Mapbox GL JS могут быть:
Data-driven styling наиболее полно раскрывается на векторных источниках, где каждый feature содержит набор атрибутов, доступных через expressions.
map.addSource('places', {
type: 'geojson',
data: '/data/places.geojson'
});
Вычисление выражений происходит на уровне рендеринга, поэтому важно учитывать:
Каждое выражение пересчитывается при изменении состояния карты (zoom, pan, feature-state), что влияет на частоту перерисовки слоя.
Стили могут формироваться программно на основе внешних данных:
const maxValue = Math.max(...values);
const style = [
'interpolate',
['linear'],
['get', 'value'],
0, '#f0f9ff',
maxValue, '#075985'
];
map.setPaintProperty('layer-id', 'fill-color', style);
Такой подход позволяет связывать визуализацию с аналитическими вычислениями вне карты.
Data-driven styling часто применяется для построения тематических карт с несколькими слоями:
Каждый слой использует собственные выражения, но опирается на единый источник данных или связанные наборы атрибутов, обеспечивая согласованную визуальную модель.