Система цветов в библиотеке Nivo поддерживает динамическое управление палитрой через данные, темы, вычисляемые функции и наследование свойств. Один из наиболее важных механизмов — привязка цвета к переменной. Такой подход позволяет визуально связывать категории, состояния, значения или группы данных с определёнными цветами без ручного описания каждого элемента.
Во всех графиках Nivo цвет обычно задаётся через свойство
colors. Оно поддерживает несколько форматов:
Простейший пример:
<ResponsiveBar
data={data}
keys={['sales']}
indexBy="month"
colors="#3b82f6"
/>
В этом случае все столбцы будут окрашены одинаково.
Наиболее распространённый способ — использование поля объекта данных как источника цвета.
const data = [
{
country: 'Germany',
population: 83,
color: '#2563eb'
},
{
country: 'France',
population: 67,
color: '#dc2626'
},
{
country: 'Italy',
population: 59,
color: '#16a34a'
}
]
colors<ResponsiveBar
data={data}
keys={['population']}
indexBy="country"
colors={({ data }) => data.color}
/>
Каждый элемент получает собственный цвет из свойства
color.
Nivo передаёт объект текущей точки данных в callback-функцию:
({ data }) => data.color
Таким образом:
В большинстве компонентов callback получает объект с подробной информацией:
colors={(bar) => {
console.log(bar)
return '#000'
}}
Для Bar доступны:
{
id,
value,
indexValue,
color,
data
}
Для Pie:
{
id,
label,
value,
color,
data
}
Это позволяет строить сложную цветовую логику.
const data = [
{
product: 'Laptop',
type: 'electronics',
value: 120
},
{
product: 'Table',
type: 'furniture',
value: 80
},
{
product: 'Phone',
type: 'electronics',
value: 200
}
]
const categoryColors = {
electronics: '#2563eb',
furniture: '#ca8a04'
}
<ResponsiveBar
data={data}
keys={['value']}
indexBy="product"
colors={({ data }) => categoryColors[data.type]}
/>
Теперь все элементы категории electronics будут
одинакового цвета.
Функция позволяет создавать динамическое окрашивание.
<ResponsiveBar
data={data}
keys={['value']}
indexBy="name"
colors={({ value }) => {
if (value > 100) {
return '#16a34a'
}
if (value > 50) {
return '#eab308'
}
return '#dc2626'
}}
/>
Такой подход часто используется:
colorByНекоторые компоненты поддерживают свойство colorBy.
Например:
<ResponsivePie
data={data}
colorBy="id"
/>
или
<ResponsivePie
data={data}
colorBy="label"
/>
Nivo автоматически:
Библиотека включает встроенные палитры на основе d3-scale.
<ResponsivePie
data={data}
colors={{ scheme: 'category10' }}
/>
Популярные схемы:
| Схема | Назначение |
|---|---|
category10 |
категории |
accent |
контрастные цвета |
dark2 |
тёмная палитра |
paired |
парные оттенки |
set1 |
яркие цвета |
set2 |
мягкие цвета |
nivo |
стандартная тема Nivo |
<ResponsivePie
data={data}
colorBy="id"
colors={{ scheme: 'set2' }}
/>
Здесь:
id становится ключом;id назначается цвет из
set2.Можно вручную определить палитру.
<ResponsiveBar
data={data}
keys={['value']}
indexBy="name"
colors={[
'#2563eb',
'#dc2626',
'#16a34a',
'#eab308'
]}
/>
Nivo распределит цвета по порядку.
colors={({ index }) => {
return `hsl(${index * 60}, 70%, 50%)`
}}
Каждый следующий элемент получает новый оттенок:
colors={({ value }) => {
return `rgba(37, 99, 235, ${value / 100})`
}}
Чем больше значение, тем насыщеннее элемент.
Nivo поддерживает механизм inherit.
borderColor={{
from: 'color',
modifiers: [
['darker', 1.2]
]
}}
from: 'color'Берётся основной цвет элемента, после чего применяется модификатор.
Поддерживаются:
| Модификатор | Описание |
|---|---|
darker |
затемнение |
brighter |
осветление |
opacity |
прозрачность |
labelTextColor={{
from: 'color',
modifiers: [
['darker', 2]
]
}}
const theme = {
axis: {
ticks: {
text: {
fill: '#94a3b8'
}
}
}
}
<ResponsiveLine
data={data}
theme={theme}
/>
Nivo хорошо работает с CSS Variables.
:root {
--chart-primary: #2563eb;
--chart-danger: #dc2626;
}
colors={() => {
return getComputedStyle(document.documentElement)
.getPropertyValue('--chart-primary')
}}
Обычно используется динамическая палитра.
const isDark = true
const colors = isDark
? ['#60a5fa', '#f87171']
: ['#2563eb', '#dc2626']
<ResponsivePie
data={data}
colors={colors}
/>
colors={({ data }) => {
return data.active
? '#16a34a'
: '#9ca3af'
}}
Используется для:
ResponsiveLine<ResponsiveLine
data={data}
colors={({ id }) => {
if (id === 'sales') {
return '#2563eb'
}
return '#dc2626'
}}
/>
defs и
fillКроме обычных цветов, Nivo поддерживает паттерны и градиенты.
defs={[
{
id: 'dots',
type: 'patternDots',
background: 'inherit',
color: 'rgba(255,255,255,0.3)',
size: 4,
padding: 1,
stagger: true
}
]}
fill={[
{
match: {
id: 'france'
},
id: 'dots'
}
]}
defs={[
{
id: 'gradient',
type: 'linearGradient',
colors: [
{
offset: 0,
color: '#2563eb'
},
{
offset: 100,
color: '#60a5fa'
}
]
}
]}
fill={[
{
match: '*',
id: 'gradient'
}
]}
Легенды автоматически наследуют цвет элементов.
legends={[
{
anchor: 'bottom',
direction: 'row'
}
]}
Если цвет вычисляется динамически, легенда также обновляется автоматически.
colors={({ value }) => {
if (value < 20) return '#dc2626'
if (value < 50) return '#f97316'
if (value < 80) return '#eab308'
return '#16a34a'
}}
Такой механизм особенно полезен в:
Nivo построен поверх d3, поэтому можно подключать собственные шкалы.
import { scaleSequential } from 'd3-scale'
import { interpolateBlues } from 'd3-scale-chromatic'
const colorScale = scaleSequential(interpolateBlues)
.domain([0, 100])
colors={({ value }) => colorScale(value)}
Функция colors вызывается для каждого элемента.
При больших объёмах данных желательно:
useMemo.const colorMap = useMemo(() => ({
sales: '#2563eb',
profit: '#16a34a'
}), [])
Неверно:
colors={({ data }) => {
data.color
}}
Верно:
colors={({ data }) => {
return data.color
}}
colors={({ data }) => data.backgroundColor}
Если поле отсутствует, элементы могут стать прозрачными или получить дефолтный цвет.
{
type: 'Electronics'
}
categoryColors['electronics']
Из-за разного регистра цвет не будет найден.
Крупные приложения обычно используют централизованную систему цветов.
export const chartColors = {
revenue: '#2563eb',
expenses: '#dc2626',
profit: '#16a34a'
}
После этого:
colors={({ id }) => chartColors[id]}
При интеграции с UI-библиотеками цвета обычно берутся из темы приложения.
const theme = useTheme()
colors={() => theme.palette.primary.main}
Для сложных аналитических интерфейсов часто применяется трёхуровневая структура:
const palette = {
blue: '#2563eb',
red: '#dc2626',
green: '#16a34a'
}
const semantic = {
success: palette.green,
danger: palette.red,
primary: palette.blue
}
const charts = {
sales: semantic.primary,
errors: semantic.danger
}
Такой подход делает систему визуализации масштабируемой и предсказуемой.