Визуализация данных в D3.js опирается на корректное отображение шкал, где подписи осей играют критическую роль в интерпретации графика. Числовые и временные значения требуют особого подхода, поскольку их представление должно одновременно сохранять точность и оставаться визуально читаемым при любых масштабах данных.
Базовый механизм преобразования чисел в строки в 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(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"));
Это позволяет отображать даты в сокращённом виде, например:
При плотных временных рядах используется адаптивное форматирование, где формат зависит от масштаба данных.
Пример логики выбора:
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Комбинация этих механизмов позволяет поддерживать визуальную ясность даже при больших объёмах данных и высокой плотности осей.