Привязка оси к масштабу

Оси в D3.js представляют собой визуальное отображение шкалы (scale), которая переводит значения данных в координаты пикселей. Ключевой принцип работы заключается в том, что ось не существует отдельно от масштаба: она всегда строится на основе заранее определённой шкалы и автоматически отражает её домен, диапазон и форматирование значений.


Масштаб как основа координатной системы

Перед созданием оси определяется масштаб, который задаёт преобразование данных в пиксели. Масштаб состоит из двух ключевых компонентов:

  • domain — диапазон исходных данных
  • range — диапазон пикселей на SVG-плоскости

Пример линейного масштаба:

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-группе

Ось всегда рендерится внутри 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));

Ось автоматически перестраивает:

  • позиции делений
  • количество ticks
  • подписи

Привязка оси к временным шкалам

При работе с временными данными используется специализированный масштаб:

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"));

Контроль делений через tickValues

Иногда требуется жёстко задать значения делений:

const xAxis = d3.axisBottom(xScale)
  .tickValues([10, 20, 50, 80]);

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


Взаимодействие нескольких осей

При построении координатной системы обычно используются две оси:

  • горизонтальная (x)
  • вертикальная (y)
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.


Масштабирование и пересчёт координат

При изменении размеров графика пересчитываются:

  • range масштабов
  • положение осей
  • количество делений
xScale.range([0, width]);
yScale.range([height, 0]);

После изменения диапазона оси должны быть перерисованы повторным вызовом call.


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

Оси могут включать дополнительные элементы:

  • подписи в формате логарифмов
  • пользовательские форматеры
  • кастомные интервалы ticks

Пример логарифмической оси:

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));

Таким образом ось всегда отражает текущее состояние преобразования данных.


Логика привязки как единая система

Связь оси и масштаба формирует базовую архитектуру визуализации:

  • масштаб определяет геометрию
  • ось интерпретирует шкалу
  • SVG-группа отображает результат
  • повторный вызов синхронизирует состояние

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