D3.js предоставляет набор шкал (scales), среди которых временная
шкала является ключевым инструментом для работы с датами и временными
рядами. Функция d3.scaleTime() предназначена для
преобразования значений типа Date в числовой диапазон пикселей,
обеспечивая корректное отображение временных данных на графиках.
Временная шкала отличается от линейной тем, что её входные данные
интерпретируются как объекты даты. Внутренне даты преобразуются в
числовое представление (timestamp), однако API позволяет работать
напрямую с объектами Date.
Основная идея:
const scale = d3.scaleTime()
.domain([new Date(2024, 0, 1), new Date(2024, 11, 31)])
.range([0, 800]);
Любая дата внутри указанного интервала будет линейно отображаться в диапазон от 0 до 800.
d3.scaleTime() опирается на линейную интерполяцию
временных значений. Каждая дата приводится к количеству миллисекунд с
начала эпохи Unix:
Преобразование можно описать так:
f(date) = a * t + b
где t — timestamp даты.
Временная шкала является двунаправленной:
scale(date) → координатаscale.invert(value) → датаconst scale = d3.scaleTime()
.domain([new Date(2023, 0, 1), new Date(2023, 0, 10)])
.range([0, 900]);
const x = scale(new Date(2023, 0, 5));
const date = scale.invert(450);
Обратное преобразование особенно важно при обработке событий мыши на графиках.
Временные шкалы тесно связаны с интервалами времени:
D3.js автоматически поддерживает корректное распределение таких
интервалов при использовании осей (d3.axisBottom,
d3.axisLeft).
const xScale = d3.scaleTime()
.domain([new Date(2025, 0, 1), new Date(2025, 6, 1)])
.range([0, 1000]);
const xAxis = d3.axisBottom(xScale)
.ticks(d3.timeMonth.every(1));
Отображение дат на оси требует форматирования. Для этого используется
d3.timeFormat():
const format = d3.timeFormat("%Y-%m");
const xAxis = d3.axisBottom(scale)
.tickFormat(format);
Основные спецификаторы:
%Y — год%m — месяц%d — день%H — часы%M — минутыОдной из сильных сторон временной шкалы является автоматический подбор “красивых” делений:
const axis = d3.axisBottom(scale)
.ticks(d3.timeDay.every(2));
Система выбирает оптимальные значения, учитывая:
В D3.js существуют две версии временных шкал:
d3.scaleTime() — локальное времяd3.scaleUtc() — UTC без учёта часовых поясовРазница критична при работе с глобальными данными.
const local = d3.scaleTime();
const utc = d3.scaleUtc();
Использование UTC исключает сдвиги, вызванные локальными настройками системы.
const data = [
{ date: new Date(2024, 0, 1), value: 10 },
{ date: new Date(2024, 1, 1), value: 25 },
{ date: new Date(2024, 2, 1), value: 18 }
];
const x = d3.scaleTime()
.domain(d3.extent(data, d => d.date))
.range([0, 600]);
const y = d3.scaleLinear()
.domain([0, d3.max(data, d => d.value)])
.range([300, 0]);
Такой подход используется для построения линейных графиков временных рядов.
Временная шкала не просто интерполирует значения, но и учитывает календарные особенности:
Это отличает её от простой линейной шкалы.
При масштабировании графиков временная шкала используется как основа трансформации:
const zoomed = d3.event.transform.rescaleX(xScale);
Это позволяет сохранять корректное соответствие дат и координат при изменении масштаба.
Datedomain (например, строки вместо
дат)Временная шкала не зависит от равномерности данных. Даже если между точками есть большие промежутки времени, отображение остаётся линейным по времени, а не по индексу массива.
const sparseData = [
{ date: new Date(2024, 0, 1), value: 10 },
{ date: new Date(2024, 5, 1), value: 40 }
];
Расстояние между точками на графике будет пропорционально реальному времени между датами.
Временная шкала часто используется вместе с:
d3.scaleLinear() — для значенийd3.scaleLog() — для экспоненциальных данныхd3.scaleBand() — для категорий по времени (например,
дни недели)D3.js эффективно обрабатывает большие временные наборы данных за счёт:
Однако при миллионах точек требуется предварительная агрегация.
При обработке событий мыши временная шкала позволяет преобразовывать координаты в даты:
svg.on("mousemove", (event) => {
const x = d3.pointer(event)[0];
const date = scale.invert(x);
});
Это используется в интерактивных графиках, таймлайнах и финансовых приложениях.