Компонент Line в библиотеке Nivo ориентирован на отображение временных рядов и любых последовательных числовых зависимостей. Основой визуализации является массив серий, где каждая серия содержит набор точек.
Типичная структура данных:
const data = [
{
id: "series-1",
color: "hsl(210, 70%, 50%)",
data: [
{ x: "Jan", y: 12 },
{ x: "Feb", y: 18 },
{ x: "Mar", y: 25 }
]
},
{
id: "series-2",
data: [
{ x: "Jan", y: 8 },
{ x: "Feb", y: 14 },
{ x: "Mar", y: 20 }
]
}
];
Каждый объект верхнего уровня представляет отдельную линию графика.
Поле id используется для легенды, тултипов и внутренних
ключей React. Массив data определяет координаты точек,
где:
x — категориальная или числовая осьy — числовое значениеКомпонент ResponsiveLine является основной точкой входа.
Он автоматически адаптируется к размерам контейнера.
import { ResponsiveLine } from '@nivo/line';
const MyLineChart = () => (
<div style={{ height: 400 }}>
<ResponsiveLine
data={data}
margin={{ top: 50, right: 110, bottom: 50, left: 60 }}
/>
</div>
);
Ключевой параметр — margin, который управляет отступами
графика внутри контейнера. Недостаточный отступ приводит к обрезанию
осей и подписей.
В Nivo масштабирование задаётся через параметр xScale и
yScale.
xScale={{
type: 'point'
}}
yScale={{
type: 'linear',
min: 'auto',
max: 'auto',
stacked: false,
reverse: false
}}
Тип point используется для категориальных значений по
оси X. Для числовых данных может применяться linear или
time.
xScale={{
type: 'time',
format: '%Y-%m-%d',
precision: 'day'
}}
Временные шкалы требуют строгого формата данных и используются для финансовых и аналитических графиков.
Оси управляют отображением подписей и сетки.
axisBottom={{
orient: 'bottom',
tickSize: 5,
tickPadding: 5,
tickRotation: 0,
legend: 'Период',
legendOffset: 36,
legendPosition: 'middle'
}}
axisLeft={{
orient: 'left',
tickSize: 5,
tickPadding: 5,
tickRotation: 0,
legend: 'Значение',
legendOffset: -40,
legendPosition: 'middle'
}}
Основные параметры:
tickSize — длина деленийtickPadding — расстояние от подписей до осиtickRotation — поворот текстаlegend — подпись осиlegendOffset — смещение легендыГрафическое представление линий регулируется через ряд параметров.
curve="monotoneX"
lineWidth={2}
enablePoints={true}
pointSize={8}
pointColor={{ theme: 'background' }}
pointBorderWidth={2}
pointBorderColor={{ from: 'serieColor' }}
Параметр curve определяет интерполяцию линии:
linear — прямые сегментыmonotoneX — сглаживание без резких изгибовbasis — плавная B-spline криваяcardinal — управляемая кривизнаВыбор кривой влияет на восприятие тренда: линейный вариант сохраняет точность, сглаженные — визуальную читаемость.
Точки данных играют ключевую роль в интерпретации графика.
enablePoints={true}
pointSize={10}
pointLabel="y"
Дополнительные параметры:
pointLabel — отображаемое значение внутри точкиpointLabelYOffset — вертикальное смещение подписиТочки могут быть отключены при большом количестве данных для повышения производительности.
Цветовая схема задаётся через colors:
colors={{ scheme: 'nivo' }}
Возможны варианты:
(serie) => colornivo, category10,
dark2)Пример динамической раскраски:
colors={({ id }) =>
id === 'series-1' ? '#ff4d4f' : '#1890ff'
}
Заливка под линией усиливает визуальную выразительность.
enableArea={true}
areaOpacity={0.15}
При нескольких сериях важно учитывать наложение областей. В таких случаях часто применяется прозрачность ниже 0.2.
Сетка помогает ориентироваться в значениях.
enableGridX={false}
enableGridY={true}
При плотных данных сетку по X часто отключают для уменьшения визуального шума.
Tooltip формируется автоматически, но может быть переопределён.
tooltip={({ point }) => (
<div>
<strong>{point.serieId}</strong>
<div>{point.data.x}: {point.data.y}</div>
</div>
)}
Структура point содержит:
serieIddata.xdata.yЛегенда позволяет идентифицировать серии.
legends={[
{
anchor: 'bottom-right',
direction: 'column',
translateX: 100,
itemWidth: 80,
itemHeight: 20,
symbolSize: 12,
symbolShape: 'circle'
}
]}
Позиционирование легенды критично при большом количестве серий, чтобы избежать перекрытия графика.
Для повышения точности наведения используется
enablePointLabel и useMesh.
useMesh={true}
Mesh создаёт невидимую сетку взаимодействия, позволяя определять ближайшую точку даже при отсутствии прямого попадания курсора.
Срезы позволяют анализировать значения по вертикали или горизонтали.
enableSlices="x"
Возможные режимы:
x — вертикальный срез по оси Xy — горизонтальный срез по оси YСрезы упрощают сравнение нескольких серий в одной точке времени.
Глобальная стилизация графика осуществляется через
theme.
theme={{
axis: {
ticks: {
text: {
fontSize: 12,
fill: '#333'
}
}
},
grid: {
line: {
stroke: '#eee',
strokeWidth: 1
}
}
}}
Темизация охватывает:
Для сложных визуализаций используются SVG-градиенты.
defs={[
{
id: 'gradientA',
type: 'linearGradient',
colors: [
{ offset: 0, color: '#4f46e5' },
{ offset: 100, color: '#06b6d4' }
]
}
]}
Применение:
fill={[{ match: '*', id: 'gradientA' }]}
Градиенты усиливают визуальную иерархию при отображении нескольких линий.
При увеличении количества точек наблюдается деградация производительности. Основные методы оптимизации:
enablePoints={false})useMesh вместо большого числа
DOM-элементовlinear)Также важно учитывать, что временные шкалы требуют дополнительной обработки данных, что влияет на рендеринг.
При комбинированных шкалах возможно использование кастомных форматтеров:
axisBottom={{
format: value => `${value} г.`
}}
Форматирование позволяет адаптировать отображение под финансовые или аналитические данные, где стандартные подписи недостаточны.
При включении stacked значения суммируются:
yScale={{
stacked: true
}}
Такой режим используется для анализа структуры вкладов или распределений. Однако он изменяет интерпретацию оси Y, так как значения становятся накопительными.
ResponsiveLine требует родительского контейнера с явно
заданной высотой.
<div style={{ height: 500 }}>
<ResponsiveLine data={data} />
</div>
Отсутствие высоты приводит к нулевому рендеру, поскольку библиотека рассчитывает размеры на основе контейнера.
Серии могут динамически скрываться через фильтрацию данных перед
передачей в компонент. Внутренние механизмы Nivo не управляют состоянием
видимости, поэтому контроль осуществляется на уровне массива
data.
const filteredData = data.filter(d => d.id !== 'series-2');
Такой подход позволяет реализовывать кастомные переключатели серий вне компонента графика.