Компонент Line: базовая конфигурация

Компонент 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 — числовое значение

Базовая конфигурация компонента Line

Компонент 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'
}}

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

Настройка осей (axis)

Оси управляют отображением подписей и сетки.

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)

Параметр curve определяет интерполяцию линии:

  • linear — прямые сегменты
  • monotoneX — сглаживание без резких изгибов
  • basis — плавная B-spline кривая
  • cardinal — управляемая кривизна

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

Работа с точками (points)

Точки данных играют ключевую роль в интерпретации графика.

enablePoints={true}
pointSize={10}
pointLabel="y"

Дополнительные параметры:

  • pointLabel — отображаемое значение внутри точки
  • pointLabelYOffset — вертикальное смещение подписи

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

Цвета и тематизация

Цветовая схема задаётся через colors:

colors={{ scheme: 'nivo' }}

Возможны варианты:

  • массив цветов
  • функция (serie) => color
  • предустановленные схемы (nivo, category10, dark2)

Пример динамической раскраски:

colors={({ id }) =>
  id === 'series-1' ? '#ff4d4f' : '#1890ff'
}

Область под линией (area)

Заливка под линией усиливает визуальную выразительность.

enableArea={true}
areaOpacity={0.15}

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

Сетка (grid)

Сетка помогает ориентироваться в значениях.

enableGridX={false}
enableGridY={true}

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

Подсказки (tooltip)

Tooltip формируется автоматически, но может быть переопределён.

tooltip={({ point }) => (
  <div>
    <strong>{point.serieId}</strong>
    <div>{point.data.x}: {point.data.y}</div>
  </div>
)}

Структура point содержит:

  • serieId
  • data.x
  • data.y
  • цвет линии
  • индекс точки

Легенда (legends)

Легенда позволяет идентифицировать серии.

legends={[
  {
    anchor: 'bottom-right',
    direction: 'column',
    translateX: 100,
    itemWidth: 80,
    itemHeight: 20,
    symbolSize: 12,
    symbolShape: 'circle'
  }
]}

Позиционирование легенды критично при большом количестве серий, чтобы избежать перекрытия графика.

Интерактивность и mesh

Для повышения точности наведения используется enablePointLabel и useMesh.

useMesh={true}

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

Срезы данных (slices)

Срезы позволяют анализировать значения по вертикали или горизонтали.

enableSlices="x"

Возможные режимы:

  • x — вертикальный срез по оси X
  • y — горизонтальный срез по оси Y

Срезы упрощают сравнение нескольких серий в одной точке времени.

Темизация (theme)

Глобальная стилизация графика осуществляется через theme.

theme={{
  axis: {
    ticks: {
      text: {
        fontSize: 12,
        fill: '#333'
      }
    }
  },
  grid: {
    line: {
      stroke: '#eee',
      strokeWidth: 1
    }
  }
}}

Темизация охватывает:

  • оси
  • сетку
  • легенды
  • тултипы

Градиенты и defs

Для сложных визуализаций используются 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 режим

При включении stacked значения суммируются:

yScale={{
  stacked: true
}}

Такой режим используется для анализа структуры вкладов или распределений. Однако он изменяет интерпретацию оси Y, так как значения становятся накопительными.

Адаптация под responsive контейнер

ResponsiveLine требует родительского контейнера с явно заданной высотой.

<div style={{ height: 500 }}>
  <ResponsiveLine data={data} />
</div>

Отсутствие высоты приводит к нулевому рендеру, поскольку библиотека рассчитывает размеры на основе контейнера.

Управление отображением серий

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

const filteredData = data.filter(d => d.id !== 'series-2');

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