Оси в D3.js представляют собой визуальное отображение шкалы (scale), которая переводит значения данных в координаты пикселей. Ключевой принцип работы заключается в том, что ось не существует отдельно от масштаба: она всегда строится на основе заранее определённой шкалы и автоматически отражает её домен, диапазон и форматирование значений.
Перед созданием оси определяется масштаб, который задаёт преобразование данных в пиксели. Масштаб состоит из двух ключевых компонентов:
Пример линейного масштаба:
const xScale = d3.scaleLinear()
.domain([0, 100])
.range([0, 500]);
В этом случае значение 0 будет отображаться в пикселе
0, а 100 — в пикселе 500. Все
промежуточные значения интерполируются линейно.
Ось создаётся как функция, которая принимает масштаб и генерирует визуальные элементы: линии делений, подписи и вспомогательную сетку.
const xAxis = d3.axisBottom(xScale);
Здесь происходит ключевая привязка: ось начинает использовать правила
преобразования, заданные масштабом xScale.
Функция оси не возвращает DOM-элемент напрямую. Она является генератором, который применяется к выбранному SVG-элементу:
svg.append("g")
.call(xAxis);
Метод call передаёт группу <g> в
функцию оси, которая наполняет её соответствующими элементами.
Ориентация оси определяет направление размещения подписей и делений:
d3.axisBottom(scale) — ось снизуd3.axisTop(scale) — ось сверхуd3.axisLeft(scale) — ось слеваd3.axisRight(scale) — ось справаКаждая ориентация влияет только на визуальное расположение элементов, но не на сам масштаб.
Пример вертикальной оси:
const yAxis = d3.axisLeft(yScale);
Ось автоматически вычисляет деления (ticks) на основе масштаба. Для линейного масштаба используются алгоритмы выбора «красивых» чисел, упрощающих восприятие данных.
xAxis.ticks(5);
Параметр задаёт приблизительное количество делений, но фактическое число может отличаться в зависимости от алгоритма оптимизации.
Масштаб определяет числовую интерпретацию, а ось отвечает за форматирование отображаемого текста.
const xAxis = d3.axisBottom(xScale)
.tickFormat(d => `${d}%`);
Здесь происходит разделение ответственности:
Ось всегда рендерится внутри SVG <g> элемента.
Этот элемент играет роль контейнера, в который D3.js помещает линии,
подписи и вспомогательные элементы.
svg.append("g")
.attr("transform", "translate(0, 300)")
.call(d3.axisBottom(xScale));
Смещение через transform критично: оно определяет
положение оси внутри графика, но не влияет на сам масштаб.
Одним из ключевых свойств осей в D3.js является реактивность к изменению масштаба. При обновлении domain или range необходимо повторно вызвать ось.
xScale.domain([0, 200]);
svg.select(".x-axis")
.call(d3.axisBottom(xScale));
Ось автоматически перестраивает:
При работе с временными данными используется специализированный масштаб:
const timeScale = d3.scaleTime()
.domain([new Date(2020, 0, 1), new Date(2021, 0, 1)])
.range([0, 800]);
Ось автоматически интерпретирует даты:
const timeAxis = d3.axisBottom(timeScale);
Форматирование может быть уточнено:
d3.axisBottom(timeScale)
.tickFormat(d3.timeFormat("%Y-%m"));
Иногда требуется жёстко задать значения делений:
const xAxis = d3.axisBottom(xScale)
.tickValues([10, 20, 50, 80]);
В этом случае алгоритм автоматического выбора отключается, и ось строго следует заданным значениям.
При построении координатной системы обычно используются две оси:
const xAxis = d3.axisBottom(xScale);
const yAxis = d3.axisLeft(yScale);
svg.append("g")
.attr("class", "x-axis")
.attr("transform", "translate(0, 400)")
.call(xAxis);
svg.append("g")
.attr("class", "y-axis")
.call(yAxis);
Каждая ось строго связана со своим масштабом, и пересечение происходит только в визуальной системе координат SVG.
При изменении размеров графика пересчитываются:
xScale.range([0, width]);
yScale.range([height, 0]);
После изменения диапазона оси должны быть перерисованы повторным
вызовом call.
Оси могут включать дополнительные элементы:
Пример логарифмической оси:
const logScale = d3.scaleLog()
.domain([1, 1000])
.range([0, 500]);
const logAxis = d3.axisBottom(logScale)
.ticks(10, ",.1s");
SVG-группа <g> позволяет логически объединить все
элементы оси:
Каждый вызов оси перезаписывает содержимое группы, обеспечивая синхронизацию с масштабом без ручного управления DOM.
Ось часто используется совместно с grid lines:
d3.axisBottom(xScale)
.tickSize(-height)
.tickFormat("");
В этом случае деления превращаются в сетку, но остаются привязанными к тому же масштабу.
При зумировании или панорамировании масштаб изменяется динамически:
const newX = transform.rescaleX(xScale);
svg.select(".x-axis")
.call(d3.axisBottom(newX));
Таким образом ось всегда отражает текущее состояние преобразования данных.
Связь оси и масштаба формирует базовую архитектуру визуализации:
Эта структура обеспечивает устойчивую модель визуализации, в которой изменение данных автоматически приводит к корректному обновлению графического представления.