Nivo предоставляет несколько уровней управления цветом, где ключевой принцип заключается в разделении визуального слоя и данных. Цветовая привязка в библиотеке строится вокруг двух базовых подходов: идентификации по ключу (id-based coloring) и вычисления на основе значения (value-based coloring). Эти механизмы могут использоваться независимо или комбинироваться, формируя гибкую систему визуальной кодировки данных.
В основе цветового механизма лежит функция color,
которая вызывается для каждого элемента визуализации. В зависимости от
компонента (bar, pie, line, heatmap) входные данные могут отличаться, но
логика остается единообразной: каждый элемент получает доступ к
datum, из которого извлекается либо ключ, либо числовое
значение.
Типовая сигнатура:
color: (datum) => string
или через декларативные параметры:
colors: { scheme: 'nivo' }
или:
colors: { datum: 'id' }
Самый распространенный сценарий — привязка цвета к идентификатору
серии или категории. В этом случае каждый уникальный 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 поддерживает предустановленные схемы через модуль цветов:
nivo, set1,
set2, set3, category10blues, greens,
orangesred_yellow_blue,
brown_blueGreenПример:
colors={{ scheme: 'blues' }}
Схемы особенно важны в случаях, когда нет явной бизнес-логики для цветов, и требуется равномерное распределение оттенков.
При использовании схемы библиотека генерирует массив цветов и маппит их по индексам или ключам.
В отличие от 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={(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)`
}}
Этот подход часто применяется в сложных дашбордах, где стандартные палитры недостаточны.
В реальных интерфейсах часто комбинируются несколько стратегий:
Пример комбинированной логики:
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={{
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При выполнении этих условий визуализация сохраняет семантическую целостность даже при динамическом обновлении данных.