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

Компонент ScatterPlot в библиотеке Nivo предназначен для отображения точечных диаграмм, где каждая точка представляет собой объект с координатами в двумерном пространстве. Базовая конфигурация начинается с правильного определения структуры входных данных, так как именно она определяет корректность дальнейшего рендеринга.

Основной формат данных представляет собой массив серий:

const data = [
  {
    id: 'series A',
    data: [
      { x: 1, y: 2 },
      { x: 2, y: 3 },
      { x: 3, y: 5 }
    ]
  },
  {
    id: 'series B',
    data: [
      { x: 1, y: 5 },
      { x: 2, y: 1 },
      { x: 3, y: 4 }
    ]
  }
]

Каждый объект верхнего уровня описывает отдельную серию, а вложенный массив data содержит координаты точек. Значения x и y могут быть числовыми, временными или категориальными в зависимости от конфигурации шкал.

Подключение компонента ScatterPlot

Использование ScatterPlot начинается с импорта компонента:

import { ResponsiveScatterPlot } from '@nivo/scatterplot'

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

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

Минимальная рабочая конфигурация включает данные, размеры и базовые параметры отображения:

<ResponsiveScatterPlot
  data={data}
  margin={{ top: 40, right: 40, bottom: 60, left: 60 }}
  xScale={{ type: 'linear', min: 0, max: 'auto' }}
  yScale={{ type: 'linear', min: 0, max: 'auto' }}
  axisBottom={{
    legend: 'ось X',
    legendPosition: 'middle',
    legendOffset: 46
  }}
  axisLeft={{
    legend: 'ось Y',
    legendPosition: 'middle',
    legendOffset: -50
  }}
/>

Ключевые параметры:

  • data — источник данных
  • margin — отступы графика внутри контейнера
  • xScale / yScale — тип и диапазон шкал
  • axisBottom / axisLeft — настройка осей

Настройка шкал (Scales)

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

Линейная шкала

Наиболее распространённый вариант:

xScale={{ type: 'linear', min: 0, max: 'auto' }}
yScale={{ type: 'linear', min: 0, max: 'auto' }}

Значение auto позволяет библиотеке автоматически вычислять максимальные границы на основе данных.

Логарифмическая шкала

Используется при работе с большими диапазонами значений:

xScale={{ type: 'log', base: 10, min: 1, max: 10000 }}

Логарифмическая шкала требует, чтобы значения были строго положительными.

Временная шкала

При работе с датами:

xScale={{
  type: 'time',
  format: 'native',
  precision: 'day'
}}

В этом случае значения x должны быть объектами Date.

Настройка осей

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

Нижняя ось

axisBottom={{
  legend: 'Время',
  legendPosition: 'middle',
  legendOffset: 50,
  tickSize: 5,
  tickPadding: 5,
  tickRotation: 0
}}

Левая ось

axisLeft={{
  legend: 'Значение',
  legendPosition: 'middle',
  legendOffset: -50
}}

Дополнительные параметры позволяют управлять внешним видом делений, их поворотом и отступами.

Управление внешним видом точек

Каждая точка на графике может быть стилизована через параметры компонента:

nodeSize={12}
colors={{ scheme: 'nivo' }}
blendMode="multiply"
  • nodeSize определяет размер маркеров
  • colors задаёт цветовую схему или функцию окрашивания
  • blendMode управляет режимом наложения цветов

Расширенная настройка цвета:

colors={d => d.seriesId === 'series A' ? '#ff4d4d' : '#4d79ff'}

Взаимодействие и всплывающие подсказки

Tooltip позволяет отображать дополнительную информацию при наведении:

tooltip={({ node }) => (
  <div style={{ padding: 12, background: '#fff' }}>
    <strong>{node.serieId}</strong><br />
    x: {node.data.x}<br />
    y: {node.data.y}
  </div>
)}

Поведение tooltip полностью настраиваемо, включая форматирование и стили.

Использование mesh для повышения точности hover

Параметр useMesh улучшает область захвата событий мыши:

useMesh={true}

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

Настройка маргин и компоновки

Правильные отступы критичны для читаемости графика:

margin={{
  top: 50,
  right: 50,
  bottom: 80,
  left: 80
}}

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

Легенды и группировка серий

Легенды позволяют различать серии данных:

legends={[
  {
    anchor: 'bottom-right',
    direction: 'column',
    translateX: 130,
    itemWidth: 100,
    itemHeight: 12,
    itemsSpacing: 5,
    symbolSize: 12
  }
]}

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

Анимация и переходы

Компонент поддерживает встроенные анимации:

animate={true}
motionConfig="gentle"

Тип motionConfig влияет на плавность переходов между состояниями данных.

Работа с темами

Тематизация позволяет унифицировать внешний вид графиков:

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

Через theme можно контролировать сетку, подписи, легенды и tooltip.

Частые ошибки базовой конфигурации

Неправильное определение структуры данных:

// ошибка: отсутствует вложенный data
const data = [
  { id: 'A', x: 1, y: 2 }
]

Несоответствие типов шкал:

xScale={{ type: 'linear' }}
// при этом x = new Date() -> приведёт к некорректному отображению

Отсутствие margin:

margin={{ top: 0, right: 0, bottom: 0, left: 0 }}

Это приводит к визуальному наложению элементов графика на границы контейнера.

Минимальный итоговый пример конфигурации

<ResponsiveScatterPlot
  data={data}
  margin={{ top: 40, right: 40, bottom: 60, left: 60 }}
  xScale={{ type: 'linear', min: 0, max: 'auto' }}
  yScale={{ type: 'linear', min: 0, max: 'auto' }}
  nodeSize={10}
  useMesh={true}
  axisBottom={{ legend: 'X' }}
  axisLeft={{ legend: 'Y' }}
  colors={{ scheme: 'nivo' }}
  animate={true}
/>