Runtime styling

Mapbox GL JS предоставляет механизм runtime styling — динамического изменения визуального представления карты без пересоздания стиля и перезагрузки источников данных. Этот подход опирается на концепцию декларативного описания карты через стиль (style specification) и последующую модификацию отдельных его частей в реальном времени.


В основе runtime styling лежит разделение карты на несколько независимых слоёв абстракции:

  • Style (стиль карты) — JSON-описание визуального состояния
  • Sources (источники данных) — геоданные (vector, raster, geojson)
  • Layers (слои) — визуальные представления данных
  • Paint / Layout properties — параметры отрисовки
  • Feature State — динамическое состояние объектов

Runtime styling работает поверх уже загруженного стиля и позволяет изменять любые его части через API Mapbox GL JS без полной реконфигурации карты.


Изменение стиля карты в реальном времени

Полная смена стиля

Метод setStyle полностью заменяет текущий стиль новым:

map.setStyle('mapbox://styles/mapbox/dark-v11');

Особенности:

  • удаляются все слои и источники
  • загружается новый style JSON
  • требуется повторная инициализация кастомных слоёв

При смене стиля важно учитывать событие загрузки:

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 наиболее часто используется для изменения визуальных свойств слоёв.

Paint properties

map.setPaintProperty('roads-highlight', 'line-color', '#00ff00');
map.setPaintProperty('roads-highlight', 'line-width', 4);

Paint properties отвечают за визуальные характеристики:

  • цвет
  • прозрачность
  • ширину линий
  • заливку
  • размытие

Layout 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 как основа runtime styling

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: динамическое состояние объектов

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:

  • не требует изменения GeoJSON или vector tiles
  • обновляется мгновенно
  • подходит для hover, selection, focus эффектов

Работа с источниками данных в runtime

Обновление GeoJSON источника

map.getSource('points').setData(newGeojson);

Это основной механизм обновления динамических данных:

  • realtime трекинг объектов
  • обновление пользовательских данных
  • потоковые данные

Управление слоями через условные выражения

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'
]);

Анимации через runtime styling

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'
]);

Ограничения runtime styling

Несмотря на гибкость, существуют ограничения:

  • сложные выражения влияют на производительность
  • частые вызовы setPaintProperty могут вызывать перерасчёт рендера
  • setStyle полностью сбрасывает состояние карты
  • Feature State ограничен идентификаторами объектов

Оптимизация обновлений

Батчинг изменений

map.batch(() => {
  map.setPaintProperty('roads', 'line-color', '#ff0000');
  map.setLayoutProperty('labels', 'visibility', 'none');
});

(в реальных реализациях используется минимизация количества вызовов API)


Минимизация перерисовок

Рекомендуется:

  • избегать частых обновлений в циклах
  • использовать expressions вместо JS-логики
  • обновлять state, а не стили напрямую
  • группировать изменения

Сценарии применения runtime styling

Интерактивные карты

  • hover эффекты
  • выделение объектов
  • фильтрация данных пользователем

Аналитические панели

  • визуализация KPI
  • heatmaps
  • кластеризация

Реальное время

  • транспортные системы
  • трекинг объектов
  • IoT данные

Тема интерфейса

  • переключение light/dark mode
  • адаптация под контекст

Связь runtime styling и декларативного подхода

Runtime styling сохраняет декларативную природу Mapbox GL JS:

  • стиль остаётся JSON-структурой
  • изменения не требуют императивного пересоздания карты
  • логика отображения переносится в expressions

Это делает систему предсказуемой, масштабируемой и пригодной для сложных визуализаций данных в браузере.