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

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


Числовое форматирование через d3.format

Базовый механизм преобразования чисел в строки в D3.js реализован через функцию d3.format. Она использует синтаксис, схожий с форматированием в Python и других системах визуализации.

Основная структура:

d3.format(specifier)(value)

где specifier определяет правила отображения числа.

Основные спецификаторы

Целые числа

d3.format("d")(1234)   // "1234"

Используется для отображения без дробной части.

Десятичные числа

d3.format(".2f")(12.3456)   // "12.35"

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

Сокращённые числа с SI-префиксами

d3.format(".2s")(1500000)   // "1.50M"

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

Разделители тысяч

d3.format(",")(1000000)   // "1,000,000"

Запятая в спецификаторе автоматически добавляет группировку разрядов.


Локализованное форматирование

D3 поддерживает региональные настройки через d3.formatLocale.

const locale = d3.formatLocale({
  decimal: ",",
  thousands: ".",
  grouping: [3],
  currency: ["₸", ""]
});

Созданный объект позволяет переопределять форматирование:

const format = locale.format(",.2f");
format(1234567.89)  // "1.234.567,89"

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


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

Проценты формируются с помощью спецификатора %.

d3.format(".1%")(0.456)  // "45.6%"

Значение автоматически умножается на 100 и добавляется знак процента.


Управление числовыми подписями осей

Оси создаются через d3.axisBottom, d3.axisLeft и аналогичные функции. Форматирование подписей подключается через метод tickFormat.

const axis = d3.axisBottom(scale)
  .tickFormat(d3.format(".2s"));

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


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

Для работы с датами используется отдельный механизм — d3.timeFormat, основанный на спецификаторах времени.

d3.timeFormat(specifier)(date)

Основные спецификаторы времени

Год

d3.timeFormat("%Y")(new Date())  // "2026"

Месяц и день

d3.timeFormat("%d.%m")(new Date())  // "16.05"

Полная дата

d3.timeFormat("%Y-%m-%d")(new Date())  // "2026-05-16"

Время

d3.timeFormat("%H:%M:%S")(new Date())  // "14:35:12"

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

Для временных шкал используется d3.axisBottom совместно с d3.scaleTime.

const xAxis = d3.axisBottom(timeScale)
  .tickFormat(d3.timeFormat("%b %Y"));

Это позволяет отображать даты в сокращённом виде, например:

  • Jan 2024
  • Feb 2024
  • Mar 2024

Автоматическое масштабирование временных подписей

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

Пример логики выбора:

function formatDate(date) {
  const formatMinute = d3.timeFormat("%H:%M");
  const formatDay = d3.timeFormat("%d %b");
  const formatMonth = d3.timeFormat("%b %Y");

  if (timeScale.ticks(d3.timeHour).length < 10) return formatMinute(date);
  if (timeScale.ticks(d3.timeDay).length < 10) return formatDay(date);
  return formatMonth(date);
}

Такой подход предотвращает перегрузку оси лишними деталями.


Комбинированное форматирование чисел и времени

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

Пример:

const xAxis = d3.axisBottom(timeScale)
  .tickFormat(d3.timeFormat("%d.%m"));

const yAxis = d3.axisLeft(valueScale)
  .tickFormat(d3.format(".1s"));

В этом случае временная ось отображает даты, а числовая — компактные значения с SI-префиксами.


Кастомные функции форматирования

D3 позволяет полностью заменить стандартное форматирование функцией.

.tickFormat(d => `$${d.toFixed(2)}`)

или для сложных условий:

.tickFormat(d => {
  if (d > 1e6) return d3.format(".2s")(d);
  if (d > 1e3) return d3.format(",")(d);
  return d.toString();
});

Такой подход применяется при нестандартных бизнес-логиках отображения данных.


Форматирование дробных временных интервалов

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

d3.timeFormat("%H:%M:%S.%L")

где %L обозначает миллисекунды.

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


Управление читаемостью подписей

Числовые и временные подписи должны оставаться читаемыми при любых масштабах. Для этого применяются:

  • сокращение чисел через .s
  • ограничение количества знаков через .f
  • адаптивные временные форматы
  • кастомные функции форматирования
  • локализация разделителей

Комбинация этих механизмов позволяет поддерживать визуальную ясность даже при больших объёмах данных и высокой плотности осей.