Цветовые градиенты

Цветовые градиенты в Mapbox GL JS строятся на основе системы выражений (expressions), которая позволяет вычислять визуальные свойства динамически, в зависимости от данных, масштаба и других параметров карты. Градиенты применяются не как статическая заливка, а как функция интерполяции между значениями, что обеспечивает плавные переходы цвета на линиях, полигонах, тепловых слоях и 3D-объектах.

Основой градиентных эффектов в Mapbox GL JS являются свойства paint, поддерживающие выражения interpolate, step, match, а также специализированные параметры вроде line-gradient и heatmap-color.


Система выражений и роль интерполяции

Градиенты в Mapbox GL JS почти всегда опираются на интерполяцию числовых значений в цветовое пространство.

Интерполяция через interpolate

y = interpolate(linear, x, x_0, c_0, x_1, c_1, )

Функция interpolate принимает входное значение (например, плотность объектов, zoom или высоту) и преобразует его в цвет, плавно переходя между контрольными точками.

Пример использования:

map.setPaintProperty('layer-id', 'fill-color', [
  'interpolate',
  ['linear'],
  ['get', 'value'],
  0, '#2DC4B2',
  50, '#3BB3C3',
  100, '#669EC4',
  200, '#8B88B6',
  300, '#A2719B'
]);

Здесь значение value из данных управляет цветом полигона, создавая непрерывный градиент.


Градиенты для линий: line-gradient

Одним из наиболее мощных инструментов является свойство line-gradient, которое позволяет создавать градиент вдоль геометрии линии, а не только на основе атрибутов данных.

Для его работы требуется использование источника geojson с параметром lineMetrics: true.

map.addSource('route', {
  type: 'geojson',
  lineMetrics: true,
  data: {
    type: 'Feature',
    geometry: {
      type: 'LineString',
      coordinates: [
        [37.62, 55.75],
        [37.64, 55.76],
        [37.66, 55.77]
      ]
    }
  }
});

Далее применяется выражение:

map.addLayer({
  id: 'route-line',
  type: 'line',
  source: 'route',
  paint: {
    'line-width': 6,
    'line-gradient': [
      'interpolate',
      ['linear'],
      ['line-progress'],
      0, '#00c6ff',
      1, '#0072ff'
    ]
  }
});

Ключевой момент заключается в использовании line-progress, который нормализует положение точки вдоль линии от 0 до 1. Это позволяет создавать эффект “движущегося” или плавно меняющегося цвета.


Цветовые градиенты в heatmap слоях

Heatmap-слои используют градиенты для отображения плотности точек. Здесь цвет зависит от “веса” и концентрации данных.

map.addLayer({
  id: 'heat',
  type: 'heatmap',
  source: 'points',
  paint: {
    'heatmap-weight': ['get', 'weight'],
    'heatmap-intensity': 1,
    'heatmap-color': [
      'interpolate',
      ['linear'],
      ['heatmap-density'],
      0, 'rgba(33,102,172,0)',
      0.2, 'rgb(103,169,207)',
      0.4, 'rgb(209,229,240)',
      0.6, 'rgb(253,219,199)',
      0.8, 'rgb(239,138,98)',
      1, 'rgb(178,24,43)'
    ],
    'heatmap-radius': 20
  }
});

Здесь heatmap-density автоматически вычисляется движком Mapbox и нормализуется в диапазон от 0 до 1, что делает его идеальной осью для градиентных интерполяций.


Дискретные и условные градиенты: step и match

Помимо плавной интерполяции, применяются дискретные переходы.

step

'fill-color': [
  'step',
  ['get', 'value'],
  '#2DC4B2',
  10, '#3BB3C3',
  50, '#669EC4',
  100, '#8B88B6'
]

step разбивает диапазон на зоны, каждая из которых имеет фиксированный цвет, создавая “ступенчатый” градиент.

match

Используется для категориальных данных:

'circle-color': [
  'match',
  ['get', 'type'],
  'park', '#2DC4B2',
  'water', '#3BB3C3',
  'road', '#669EC4',
  '#CCCCCC'
]

Хотя это не градиент в математическом смысле, комбинация большого числа категорий может имитировать сложные цветовые переходы.


Зависимость градиентов от масштаба карты

Градиенты могут изменяться в зависимости от zoom, что позволяет визуализировать разные уровни детализации.

'fill-color': [
  'interpolate',
  ['linear'],
  ['zoom'],
  5, '#2DC4B2',
  10, '#3BB3C3',
  15, '#8B88B6'
]

Такой подход применяется для адаптации цветовой схемы под плотность отображаемых данных: на низком масштабе используются более обобщённые оттенки, на высоком — детализированные.


Цветовые пространства и тип интерполяции

Mapbox GL JS поддерживает несколько типов интерполяции, влияющих на визуальное восприятие градиента:

  • ['linear'] — равномерный переход
  • ['exponential', base] — ускоряющийся или замедляющийся переход
  • ['cubic-bezier', x1, y1, x2, y2] — управляемая кривая

Пример экспоненциальной интерполяции:

'fill-color': [
  'interpolate',
  ['exponential', 2],
  ['get', 'value'],
  0, '#2DC4B2',
  100, '#8B88B6'
]

Экспонента усиливает различия в верхней части диапазона, что часто используется для данных с неравномерным распределением.


Многослойные градиенты и композиция

Сложные визуальные эффекты создаются за счёт наложения нескольких слоёв с различными градиентами.

Например:

  • базовый слой с приглушённым градиентом
  • поверх него слой с прозрачностью и усиленными цветами
  • дополнительный слой обводки или свечения
'fill-opacity': 0.6,
'fill-outline-color': '#000'

Композиция слоёв позволяет создавать эффекты глубины, свечения и тепловой визуализации без использования постобработки.


Градиенты в 3D extrusion

Для fill-extrusion градиенты используются для передачи высоты и плотности объектов.

'fill-extrusion-color': [
  'interpolate',
  ['linear'],
  ['get', 'height'],
  0, '#2DC4B2',
  50, '#3BB3C3',
  100, '#8B88B6'
]

Дополнительно применяется освещение:

'fill-extrusion-opacity': 0.8,
'fill-extrusion-height': ['get', 'height']

Цвет становится дополнительным измерением поверх геометрии, усиливая восприятие объёма.


Практика построения устойчивых цветовых шкал

Градиенты в Mapbox GL JS требуют нормализации входных данных. Без этого цветовые переходы становятся непропорциональными.

Типичная схема построения:

  1. Определение диапазона данных
  2. Приведение значений к шкале (0–1 или фиксированный диапазон)
  3. Выбор контрольных точек
  4. Интерполяция через interpolate

Для стабильных шкал часто используется логарифмическое преобразование:

genui{“math_block_widget_always_prefetch_v2”:{“content”:“y = (x + 1)”}}

Это позволяет сгладить влияние выбросов и сделать градиенты более читаемыми при больших разбросах значений.


Производительность при использовании градиентов

Градиентные выражения вычисляются на GPU через стильный пайплайн Mapbox GL JS. Однако сложные выражения могут влиять на производительность.

К факторам нагрузки относятся:

  • количество контрольных точек в interpolate
  • частота обновления данных
  • количество одновременно активных слоёв
  • использование get в выражениях на больших наборах данных

Оптимизация достигается за счёт:

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