Генераторы осей в D3.js предназначены для автоматического построения визуальных шкал на основе переданных масштабов (scales). Они не создают оси как геометрические объекты напрямую, а формируют набор SVG-элементов (линий, подписей, делений), привязанных к выбранной шкале и её текущему состоянию.
Основой работы генераторов осей является функция масштаба, определяющая соответствие между значениями данных и координатами в пикселях. Без масштаба генератор оси не имеет смыслового контекста, поскольку не может определить ни диапазон значений, ни их позиционирование.
Каждый генератор оси в D3 возвращает функцию, которая применяется к
выбранному SVG-контейнеру через selection.call(...). Внутри
этой функции D3 создаёт или обновляет DOM-элементы оси:
Генератор не хранит DOM напрямую, он описывает правила построения оси на основе масштаба.
axisBottom(scale) создаёт горизонтальную ось, где
подписи располагаются снизу от линии оси.
Типичное применение — ось X в декартовой системе координат.
const xScale = d3.scaleLinear()
.domain([0, 100])
.range([0, 400]);
const xAxis = d3.axisBottom(xScale);
svg.append("g")
.attr("transform", "translate(0, 300)")
.call(xAxis);
Особенности:
<g>
через transformaxisTop(scale) формирует горизонтальную ось с подписями
сверху.
Применяется в случаях, когда ось X должна находиться в верхней части графика.
const xAxisTop = d3.axisTop(xScale);
svg.append("g")
.attr("transform", "translate(0, 0)")
.call(xAxisTop);
Особенности:
axisLeft(scale) создаёт вертикальную ось,
ориентированную слева направо.
Наиболее распространённый вариант оси Y.
const yScale = d3.scaleLinear()
.domain([0, 100])
.range([300, 0]);
const yAxis = d3.axisLeft(yScale);
svg.append("g")
.attr("transform", "translate(50, 0)")
.call(yAxis);
Особенности:
range([height, 0])axisRight(scale) строит вертикальную ось, размещённую
справа.
Используется для дополнительной шкалы или вторичной метрики.
const yAxisRight = d3.axisRight(yScale);
svg.append("g")
.attr("transform", "translate(450, 0)")
.call(yAxisRight);
Особенности:
Генераторы осей полностью зависят от типа масштаба:
scaleLinear — равномерные числовые осиscaleTime — временные осиscaleBand — категориальные осиscaleLog — логарифмические осиТип масштаба определяет не только значения, но и характер делений.
Генераторы осей позволяют управлять плотностью и форматом делений.
const xAxis = d3.axisBottom(xScale)
.ticks(10);
D3 может игнорировать точное число, если оно конфликтует с читаемостью.
const xAxis = d3.axisBottom(xScale)
.tickFormat(d => `${d}%`);
или с использованием форматеров:
const xAxis = d3.axisBottom(xScale)
.tickFormat(d3.format(".2f"));
const xAxis = d3.axisBottom(xScale)
.tickValues([10, 20, 50, 80, 100]);
Этот режим полностью переопределяет автоматическую генерацию делений.
Все оси строятся внутри SVG-группы <g>.
Позиционирование осуществляется через transform, а не через
координаты отдельных элементов.
Пример базовой структуры:
<g class="x-axis">
<line class="domain"></line>
<g class="tick">
<line></line>
<text></text>
</g>
</g>
Для горизонтальных и вертикальных осей критично соблюдать корректное смещение:
translate(0, height)translate(0, 0)translate(0, 0)translate(width, 0)Оси не статичны. При изменении масштаба их необходимо перерисовывать.
xScale.domain([0, newMax]);
svg.select(".x-axis")
.transition()
.duration(750)
.call(d3.axisBottom(xScale));
При этом D3 автоматически обновляет:
Внешний вид осей контролируется через CSS:
.axis path {
stroke: #000;
}
.axis line {
stroke: #ccc;
}
.axis text {
font-size: 12px;
fill: #333;
}
Часто ось domain делают более заметной, а вспомогательные линии — приглушёнными.
Графики часто содержат несколько осей одновременно:
svg.append("g")
.attr("class", "x-axis")
.attr("transform", "translate(0, 300)")
.call(d3.axisBottom(xScale));
svg.append("g")
.attr("class", "y-axis")
.attr("transform", "translate(50, 0)")
.call(d3.axisLeft(yScale));
svg.append("g")
.attr("class", "y-axis-right")
.attr("transform", "translate(450, 0)")
.call(d3.axisRight(yScale2));
Такой подход позволяет строить многомерные визуализации с разными шкалами.
Каждый генератор оси в D3 реализует паттерн конфигурации через
замыкания. Вызов d3.axisBottom(scale) возвращает функцию с
состоянием:
Изменение параметров не создаёт новый объект, а модифицирует существующий генератор.
Ключевое различие определяется не только направлением подписи, но и логикой ориентации:
При этом математическая модель остаётся одинаковой — различие только в визуальном представлении.
Для scaleBand оси работают с центрами диапазонов
категорий:
const xScale = d3.scaleBand()
.domain(["A", "B", "C"])
.range([0, 300])
.padding(0.2);
const xAxis = d3.axisBottom(xScale);
Здесь деления соответствуют не числам, а категориям, что меняет плотность и структуру ticks.
В более сложных визуализациях оси часто отделяются логически:
<g> для каждой осиЭто позволяет масштабировать графики без разрушения DOM-структуры.
D3 минимизирует DOM-операции:
Однако при большом числе тиков может возникать нагрузка, особенно при анимации.
При ресайзе контейнера необходимо пересчитывать:
Без этого оси остаются визуально некорректными относительно графика.