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

Цветовые системы в визуализации данных на базе Nivo строятся вокруг идеи предсказуемого сопоставления значений и визуальных характеристик. Цвет здесь выступает не декоративным элементом, а семантическим кодом, который должен сохранять стабильность при изменении данных, масштабировании и переключении режимов отображения. В экосистеме Nivo это реализуется через комбинацию шкал (scales), палитр и интерполяторов, заимствованных из подходов d3-scale и d3-scale-chromatic, с дополнительными абстракциями библиотеки.

Цветовая модель в Nivo опирается на три базовых подхода:

  • Категориальные шкалы — фиксированное соответствие категорий и цветов
  • Последовательные шкалы — градиент между минимальным и максимальным значением
  • Дивергентные шкалы — баланс двух противоположных направлений относительно центра

Во всех случаях ключевым параметром выступает свойство colors, которое присутствует практически во всех визуальных компонентах: ResponsiveBar, ResponsivePie, ResponsiveHeatMap, ResponsiveChoropleth и других.

Формат colors в Nivo допускает несколько стратегий:

  • массив строк (фиксированная палитра)
  • функция (datum) => color
  • объект шкалы из @nivo/colors
  • строковый идентификатор предустановленной схемы

Такой полиморфизм позволяет унифицировать цветовое поведение для разных типов графиков.

Категориальные шкалы и палитры

Категориальные шкалы применяются для дискретных данных, где каждое значение не имеет числового смысла в контексте цвета.

Типичная конфигурация:

colors: { scheme: 'nivo' }

или использование предустановленных схем:

  • nivo
  • category10
  • accent
  • dark2
  • paired

Эти схемы основаны на фиксированных наборах оттенков, где каждый следующий элемент массива данных получает следующий цвет по индексу.

Пример поведения:

colors: ['#e8c1a0', '#f47560', '#f1e15b', '#e8a838']

Если элементов больше, чем цветов в палитре, происходит циклическое повторение.

Внутри Nivo используется механизм индексного маппинга:

color = palette[index % palette.length]

Такой подход обеспечивает стабильность визуализации при отсутствии явной привязки к ключам.

Стабилизация категориальных цветов

Для предотвращения «скачков» цветов при обновлении данных применяется ключевая стабилизация по идентификатору:

colors: { datum: 'id' }

В этом случае цвет назначается не по индексу, а по хешированию или внутреннему индексному реестру значений id.

Последовательные и непрерывные интерполяции

Последовательные шкалы применяются для числовых данных, где цвет должен отражать интенсивность или величину.

Типичный вариант:

colors: { scheme: 'blues' }

или:

colors: { scheme: 'greens' }

Эти схемы построены на интерполяции оттенков одного цветового диапазона.

Интерполяция как математическая модель

В основе лежит функция:

t ∈ [0, 1] → color

где t — нормализованное значение данных.

В d3 используется набор интерполяторов:

  • interpolateRgb
  • interpolateHsl
  • interpolateLab
  • interpolateHcl
  • interpolateViridis

Nivo абстрагирует это через @nivo/colors, позволяя задавать схемы без прямого обращения к интерполяторам.

Пример логики:

value → normalize → t → interpolate(t) → color

Логарифмическое и линейное масштабирование

Хотя Nivo не всегда явно задаёт тип шкалы в пропсе colors, поведение интерполяции зависит от нормализации входных данных. Для сильно распределённых данных применяется логарифмическая или экспоненциальная подготовка до передачи в цветовую шкалу.

Дивергентные шкалы

Дивергентные палитры используются в случаях, когда существует центральное значение и отклонения в обе стороны.

Примеры схем:

  • RdBu
  • PiYG
  • Spectral

Такие шкалы задаются через центр:

min → colorA → center → colorB → max

Логика интерполяции:

if (t < 0.5) interpolate(A, center)
else interpolate(center, B)

В Nivo это применяется в компонентах тепловых карт и географических визуализаций.

Центрирование шкалы

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

  • 0 для финансовых данных (прибыль/убыток)
  • среднее значение набора
  • медиана распределения

Функции генерации цветов и кастомные интерполяции

Помимо предустановленных схем, Nivo поддерживает передачу функций, определяющих цвет вручную.

Пример:

colors: (bar) => bar.value > 100 ? '#ff4d4d' : '#4dff88'

Такой подход полностью отключает шкалирование и передаёт контроль пользователю.

Использование d3-интерполяторов

Возможна интеграция с интерполяторами:

import { interpolatePlasma } from 'd3-scale-chromatic'

И применение:

colors: (d) => interpolatePlasma(d.value / max)

Это даёт доступ к непрерывным спектрам высокой плотности.

Кастомные градиенты

При необходимости можно строить собственные градиентные функции:

f(t) = mix(colorA, colorB, t)

где mix реализует линейную интерполяцию по RGB или HSL каналам.

Применение цветов в различных компонентах Nivo

Разные компоненты Nivo используют цветовые шкалы по-разному.

Bar и Line

В столбчатых и линейных графиках цвет обычно зависит от серии данных:

  • серия → цвет из палитры
  • точка → цвет серии

Возможна переопределённая логика:

colors: { scheme: 'set2' }

Pie и Donut

Круговые диаграммы используют категориальную шкалу с сильной визуальной различимостью.

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

  • цвет строго привязан к id
  • важна стабильность при изменении порядка данных

HeatMap

Тепловые карты используют последовательные или дивергентные шкалы.

Пример:

colors: { scheme: 'reds' }

или кастомная функция:

colors: (cell) => interpolateViridis(cell.value / max)

Choropleth

Географические карты используют нормализованные шкалы:

  • значение страны → цвет интенсивности
  • отсутствие данных → отдельный цвет (naColor)

Практика построения стабильных цветовых схем

Стабильность цветовой системы критична при динамических данных.

Основные принципы:

Привязка к идентификатору

Использование id вместо индекса:

color = map[id]

Фиксированная палитра

Избегание динамических генераторов без seed:

palette = ['#...','#...']

Ограничение количества категорий

При превышении палитры возникает повторение, что снижает читаемость.

Согласованность между графиками

Один и тот же id должен иметь одинаковый цвет во всех визуализациях.

Работа с прозрачностью и модификацией каналов

Цвета в Nivo могут модифицироваться через альфа-канал:

rgba(244, 117, 96, 0.5)

или через HSL:

hsla(12, 80%, 60%, 0.4)

Также возможна динамическая регулировка:

colors: (d) => hexToRgba(baseColor, d.opacity)

Влияние прозрачности на восприятие

Полупрозрачность используется для:

  • наложения слоёв данных
  • уменьшения визуального шума
  • выделения активных элементов

При большом количестве элементов прозрачность становится инструментом предотвращения перегрузки визуального канала.

Манипуляции яркостью и насыщенностью

Через HSL-модель возможно управление:

  • lightness для фона
  • saturation для акцентов

Пример логики:

if (selected) increase saturation
else decrease lightness

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

Цветовая система Nivo формируется как комбинация детерминированных палитр, математических интерполяций и функциональных переопределений, обеспечивая баланс между предсказуемостью и гибкостью при визуализации сложных данных.