Кастомные шкалы и форматтеры

В основе любой визуализации в Nivo лежит преобразование исходных данных в координаты пикселей. Это преобразование выполняется через шкалы (scales), которые определяют, как числовые, категориальные или временные значения отображаются на осях графика.

Nivo использует подход, основанный на D3-scale, где каждая ось графика опирается на строго определённый тип шкалы: линейную, логарифмическую, временную или категориальную. Управление этими шкалами позволяет тонко настраивать поведение диаграмм и адаптировать визуализацию под структуру данных.


Базовые типы шкал в Nivo

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

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

{
  xScale: {
    type: 'linear',
    min: 'auto',
    max: 'auto'
  }
}

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


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

Логарифмическая шкала используется для данных с экспоненциальным ростом.

{
  yScale: {
    type: 'log',
    base: 10,
    min: 1,
    max: 'auto'
  }
}

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


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

Временные шкалы применяются для осей, основанных на датах.

{
  xScale: {
    type: 'time',
    format: '%Y-%m-%d',
    precision: 'day'
  }
}

Данные интерпретируются как временные метки, что позволяет корректно отображать интервалы между датами.


Категориальная шкала

Категориальные шкалы используются для дискретных значений.

{
  xScale: {
    type: 'band',
    padding: 0.2
  }
}

Такая шкала часто применяется в bar chart и grouped bar chart, где каждая категория занимает отдельную позицию на оси.


Управление осями и форматирование значений

Шкала определяет размещение данных, но форматтеры управляют их отображением.

Форматирование подписей осей

В Nivo форматирование осей задаётся через свойства axisBottom, axisLeft и аналогичные.

axisBottom={{
  format: value => `${value} ₽`
}}

Функция format позволяет преобразовать исходное значение перед отображением. Это может быть добавление единиц измерения, округление или кастомная логика отображения.


Использование d3-format

Для сложного форматирования применяется библиотека d3-format.

import { format } from 'd3-format';

const moneyFormat = format(',.2f');

axisLeft={{
  format: value => `${moneyFormat(value)} $`
}}

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


Кастомные форматтеры значений данных

Форматирование точек (tooltips)

Tooltips часто требуют отдельного форматирования, независимого от осей.

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

Форматтер позволяет преобразовать как X, так и Y значения, а также добавить дополнительный контекст.


Форматирование в точках линий

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

pointLabel={d => `${d.y} kWh`}

Такой формат позволяет визуально закрепить значение прямо на графике.


Кастомизация шкал в различных типах графиков

Line Chart

<ResponsiveLine
  data={data}
  xScale={{
    type: 'time',
    format: 'native',
    precision: 'day'
  }}
  yScale={{
    type: 'linear',
    min: 0,
    max: 'auto'
  }}
  axisBottom={{
    format: value => new Date(value).toLocaleDateString()
  }}
/>

Временная шкала на оси X обеспечивает корректное распределение точек по времени, а форматтер оси преобразует дату в читаемый вид.


Bar Chart

<ResponsiveBar
  data={data}
  indexBy="country"
  keys={['value']}
  xScale={{
    type: 'band',
    padding: 0.3
  }}
  axisBottom={{
    format: value => value.toUpperCase()
  }}
/>

Категориальная шкала band определяет равномерное распределение столбцов, а форматтер управляет отображением категорий.


Кастомные шкалы через D3 напрямую

Nivo позволяет переопределять поведение шкал, используя кастомные D3-scale функции.

import { scaleLinear } from 'd3-scale';

const customScale = scaleLinear()
  .domain([0, 100])
  .range([0, 1]);

<ResponsiveLine
  data={data}
  xScale={customScale}
/>

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


Форматирование временных значений

Для временных шкал часто используется date-fns или стандартный Intl.DateTimeFormat.

axisBottom={{
  format: value =>
    new Intl.DateTimeFormat('ru-RU', {
      day: '2-digit',
      month: 'short'
    }).format(new Date(value))
}}

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


Кастомизация tick values

Шкалы в Nivo позволяют явно задавать значения тиков (ticks), что даёт полный контроль над разметкой осей.

axisLeft={{
  tickValues: [0, 20, 40, 60, 80, 100]
}}

Для временных шкал можно задавать массив дат:

axisBottom={{
  tickValues: [
    '2024-01-01',
    '2024-06-01',
    '2024-12-01'
  ]
}}

Форматирование легенд и дополнительных элементов

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

legends={[
  {
    anchor: 'bottom',
    direction: 'row',
    itemTextColor: '#999',
    formatter: value => `${value} %`
  }
]}

Это особенно полезно при работе с процентными распределениями и нормированными данными.


Условное форматирование значений

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

axisLeft={{
  format: value => {
    if (value > 1000) return `${value / 1000}k`;
    if (value > 0) return value;
    return '0';
  }
}}

Подобная логика часто используется для сокращённого отображения больших чисел.


Форматирование и шкалы в комбинированных графиках

В комбинированных визуализациях (line + bar) важно синхронизировать шкалы и форматтеры, чтобы избежать несоответствий в восприятии данных.

xScale={{
  type: 'point'
}}

axisBottom={{
  format: value => `Q${value}`
}}

Шкала point фиксирует категории без интерполяции, а форматтер задаёт бизнес-уровень представления данных.


Разделение ответственности между шкалой и форматтером

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

  • шкала отвечает за позицию и масштаб
  • форматтер отвечает за читаемость
  • tooltip расширяет контекст
  • легенды связывают данные с интерпретацией

Такой подход делает визуализации устойчивыми к изменениям структуры данных и требованиям интерфейса.