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

В компонентах диаграмм Nivo управление отображением значений осей строится вокруг параметров axisBottom, axisLeft, axisTop и axisRight. Основной механизм форматирования задаётся через свойство format, которое применяется к тикетам (ticks) и позволяет преобразовывать исходные значения данных в человекочитаемый вид.

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

<ResponsiveLine
    data={data}
    margin={{ top: 50, right: 110, bottom: 50, left: 60 }}
    axisBottom={{
        legend: 'Ось X',
        legendOffset: 36,
        legendPosition: 'middle'
    }}
    axisLeft={{
        legend: 'Ось Y',
        legendOffset: -40,
        legendPosition: 'middle'
    }}
/>

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


Использование format для числовых значений

Самый прямой способ форматирования — передача функции в format. Эта функция получает текущее значение тика и возвращает строку для отображения.

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

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

Для более сложных сценариев часто используется округление:

axisLeft={{
    format: value => Math.round(value)
}}

или форматирование с фиксированной точностью:

axisLeft={{
    format: value => value.toFixed(2)
}}

Форматирование через d3-format

Внутри Nivo активно используется экосистема D3, включая библиотеку форматирования чисел d3-format. Она позволяет задавать декларативные правила форматирования, которые удобнее ручных функций.

import { format } from 'd3-format';

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

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

Шаблон ,.2f означает:

  • , — разделение тысяч
  • .2 — два знака после запятой
  • f — фиксированное десятичное представление

Другие распространённые шаблоны:

format('.0%')   // проценты без знаков после запятой
format(',.0f')  // целые числа с разделителями тысяч
format('.2s')   // компактная запись (1.2k, 3.4M)

Использование d3-format обеспечивает единообразие и масштабируемость при работе с большими наборами данных.


Форматирование процентов

Отображение процентов требует не только добавления символа %, но и правильного преобразования данных (обычно умножение на 100 или использование специализированного форматтера).

import { format } from 'd3-format';

const percent = format('.1%');

axisLeft={{
    format: value => percent(value)
}}

Если данные уже представлены в диапазоне 0–100, преобразование не требуется:

axisLeft={{
    format: value => `${value}%`
}}

В аналитических дашбордах важно сохранять консистентность: либо все значения в долях (0–1), либо в процентах (0–100), чтобы избежать двойного масштабирования.


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

Для временных шкал (time scale) используется форматирование дат. В Nivo это чаще всего реализуется через date-fns или встроенные функции форматирования JavaScript.

axisBottom={{
    format: value => {
        const date = new Date(value);
        return date.toLocaleDateString();
    }
}}

Более управляемый вариант — использование date-fns:

import { format } from 'date-fns';

axisBottom={{
    format: value => format(new Date(value), 'dd.MM')
}}

Часто применяются разные уровни детализации:

  • дни: dd.MM
  • месяцы: MMM yyyy
  • часы: HH:mm

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


Локализация числовых значений

Встроенный механизм Intl.NumberFormat обеспечивает локализованное форматирование чисел, включая разделители, валюты и единицы измерения.

const formatter = new Intl.NumberFormat('ru-RU');

axisLeft={{
    format: value => formatter.format(value)
}}

Для валют:

const currency = new Intl.NumberFormat('ru-RU', {
    style: 'currency',
    currency: 'RUB'
});

axisLeft={{
    format: value => currency.format(value)
}}

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


Форматирование осей с логарифмическими данными

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

axisLeft={{
    format: value => value >= 1000 ? `${value / 1000}k` : value
}}

или более универсально:

import { format } from 'd3-format';

const compact = format('.2s');

axisLeft={{
    format: value => compact(value)
}}

Компактный формат автоматически преобразует:

  • 1_000 → 1k
  • 1_000_000 → 1M

Кастомные компоненты тиков

Помимо format, Nivo позволяет полностью заменить визуализацию тика через renderTick или tickComponent. Это даёт полный контроль над отображением значений.

const CustomTick = ({ value, x, y }) => (
    <g transform={`translate(${x},${y})`}>
        <text textAnchor="middle" dominantBaseline="middle">
            {value} ед.
        </text>
    </g>
);

axisBottom={{
    renderTick: CustomTick
}}

Такой подход используется, когда требуется:

  • добавление иконок рядом со значениями
  • условное окрашивание
  • многострочные подписи
  • комбинированные форматы (например, число + статус)

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

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

axisLeft={{
    format: value => {
        if (value > 1000000) return `${value / 1000000}M`;
        if (value > 1000) return `${value / 1000}K`;
        return value;
    }
}}

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


Управление отображаемыми значениями и форматированием

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

axisBottom={{
    tickValues: 5,
    format: value => value.toFixed(0)
}}

или с фиксированным набором значений:

axisLeft={{
    tickValues: [0, 25, 50, 75, 100],
    format: value => `${value}%`
}}

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


Форматирование дробных и нестабильных значений

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

axisLeft={{
    format: value => Number(value.toFixed(3))
}}

или с округлением:

axisLeft={{
    format: value => Math.round(value * 100) / 100
}}

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


Комбинирование нескольких стратегий форматирования

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

import { format as d3Format } from 'd3-format';

const number = d3Format(',.0f');

axisLeft={{
    format: value => {
        const base = number(value);
        return `${base} ₽`;
    }
}}

или с учетом локали:

const ru = new Intl.NumberFormat('ru-RU');

axisLeft={{
    format: value => `${ru.format(value)} ₽`
}}

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


Особенности форматирования в разных типах графиков

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

В ResponsiveBar:

axisLeft={{
    format: value => `${value}%`
}}

В ResponsiveScatterPlot:

axisBottom={{
    format: value => value.toFixed(1)
}}

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