Цветовая привязка к ключам и значениям

Nivo предоставляет несколько уровней управления цветом, где ключевой принцип заключается в разделении визуального слоя и данных. Цветовая привязка в библиотеке строится вокруг двух базовых подходов: идентификации по ключу (id-based coloring) и вычисления на основе значения (value-based coloring). Эти механизмы могут использоваться независимо или комбинироваться, формируя гибкую систему визуальной кодировки данных.

В основе цветового механизма лежит функция color, которая вызывается для каждого элемента визуализации. В зависимости от компонента (bar, pie, line, heatmap) входные данные могут отличаться, но логика остается единообразной: каждый элемент получает доступ к datum, из которого извлекается либо ключ, либо числовое значение.

Типовая сигнатура:

color: (datum) => string

или через декларативные параметры:

colors: { scheme: 'nivo' }

или:

colors: { datum: 'id' }

Привязка цвета к ключам (id-based coloring)

Самый распространенный сценарий — привязка цвета к идентификатору серии или категории. В этом случае каждый уникальный id получает стабильный цвет.

Пример для bar chart:

<Bar
    data={data}
    keys={['sales', 'profit']}
    indexBy="country"
    colors={{ scheme: 'category10' }}
    colorBy="id"
/>

Здесь происходит следующее:

  • id (например, sales, profit) становится ключом раскраски
  • каждому ключу назначается цвет из палитры
  • порядок данных не влияет на итоговую раскраску

Такой подход критичен для сравнения серий между графиками: одинаковый id всегда сохраняет цветовую идентичность.

В pie chart логика аналогична:

<Pie
    data={data}
    colors={{ scheme: 'set3' }}
    colorBy="id"
/>

Каждый сектор связывается с категорией, что обеспечивает визуальную стабильность.

Использование цветовых схем

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

  • categorical: nivo, set1, set2, set3, category10
  • sequential: blues, greens, oranges
  • diverging: red_yellow_blue, brown_blueGreen

Пример:

colors={{ scheme: 'blues' }}

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

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

Привязка цвета к значениям (value-based coloring)

В отличие от id-based подхода, значение используется как числовой вход в цветовую шкалу. Это характерно для heatmap, scatter plot и некоторых кастомных bar chart конфигураций.

Пример:

<Bar
    data={data}
    indexBy="country"
    keys={['value']}
    colors={{ scheme: 'reds' }}
    colorBy="value"
/>

Здесь цвет зависит от величины value. Чем больше значение, тем интенсивнее оттенок.

Для более точного контроля используется функция:

color={(d) => `rgba(255, 0, 0, ${d.value / 100})`}

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

Пользовательские функции color accessor

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

Пример:

color={(d) => {
    if (d.data.profit > 0) return '#2ecc71'
    return '#e74c3c'
}}

Здесь цвет кодирует знак значения, а не его величину.

Другой вариант — комбинирование id и значения:

color={(d) => {
    const base = d.id === 'sales' ? 200 : 100
    return `rgb(${base}, 50, 150)`
}}

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

Смешанные стратегии привязки

В реальных интерфейсах часто комбинируются несколько стратегий:

  • id определяет базовый цвет
  • value управляет прозрачностью или насыщенностью
  • индекс влияет на оттенок

Пример комбинированной логики:

color={(d) => {
    const base = d.id === 'sales' ? 0 : 120
    const alpha = Math.min(1, d.value / 100)
    return `hsla(${base}, 70%, 50%, ${alpha})`
}}

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

Работа с палитрами и индексами

При использовании colors как массива:

colors={['#ff0000', '#00ff00', '#0000ff']}

Nivo распределяет цвета по порядку элементов. Важно учитывать, что при изменении порядка данных визуальная семантика может нарушиться.

Чтобы стабилизировать поведение, используется colorBy="id".

Взаимодействие с theme

Цвета могут переопределяться через theme:

theme={{
    axis: { ticks: { text: { fill: '#999' } } },
    legends: { text: { fill: '#333' } }
}}

Хотя theme напрямую не управляет серией цветов, он влияет на контекст восприятия: сетки, подписи и легенды должны быть согласованы с цветовой логикой графика.

Частые ошибки при цветовой привязке

Основная проблема — несогласованность ключей:

  • изменение id между рендерами приводит к перескоку цветов
  • отсутствие colorBy="id" вызывает нестабильное поведение палитры
  • смешивание схем и кастомных функций без логики приводит к визуальному шуму

Ещё одна ошибка — использование значения как цвета без нормализации:

color={(d) => `rgb(${d.value}, 0, 0)`} // некорректно при больших диапазонах

Правильный подход требует масштабирования:

color={(d) => `rgb(${Math.min(255, d.value)}, 0, 0)`}

Контроль предсказуемости визуализации

Стабильность цветовой модели достигается при соблюдении трёх условий:

  • фиксированные id для категорий
  • явное указание colorBy
  • использование ограниченного набора палитр или функций масштабирования

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