D3.js: выравнивание текстовых меток между тиками по оси
Есть ли простой способ выровнять текстовые метки между тиками?
Вот моя временная ось с надписями над тиками:
![enter image description here]()
Я хотел бы разместить эти ярлыки, как здесь:
![enter image description here]()
Ответы
Ответ 1
Я закончил с одним из советов Ларса Коттоффа.
Каждый раз, когда я call(axis)
я также настраиваю текстовые метки.
Вот упрощенный код:
function renderAxis() {
axisContainer
.transition().duration(300)
.call(axis) // draw the standart d3 axis
.call(adjustTextLabels); // adjusts text labels on the axis
}
function adjustTextLabels(selection) {
selection.selectAll('.major text')
.attr('transform', 'translate(' + daysToPixels(1) / 2 + ',0)');
}
// calculate the width of the days in the timeScale
function daysToPixels(days, timeScale) {
var d1 = new Date();
timeScale || (timeScale = Global.timeScale);
return timeScale(d3.time.day.offset(d1, days)) - timeScale(d1);
}
Обновление:
Кстати, вот календарная демонстрация, с которой я закончил: http://bl.ocks.org/oluckyman/6199145
![enter image description here]()
Ответ 2
Нет простого (то есть встроенного) способа сделать это, но вы все равно можете достичь этого. Есть несколько вариантов. Наиболее простой tickFormat
- использовать функцию tickFormat
для указания формата с подходящим количеством пробелов перед/после чисел. Это должно быть настроено вручную для каждого приложения, хотя.
В качестве альтернативы, вы можете выбрать элементы метки после того, как они были нарисованы, и добавить подходящий атрибут transform
который соответствующим образом смещает их. Опять же, это должно быть настроено вручную.
Ваш третий вариант - иметь две разные оси, одну для галочек и одну для меток. Идея состоит в том, что ось, которая обеспечивает метки, не имеет меток, а другая не имеет меток. Вам нужно было бы правильно установить значения тиков, но, по крайней мере, вам не нужно угадывать правильное смещение.
Ответ 3
Вы можете сделать это, используя axis.tickSize(major[[,minor],end])
и .tickSubdivide()
. Ваши тики устанавливаются в соответствии с основными тиками, но если вы установите высоту этих тиков на 0 и установите некоторую высоту для мелких тиков и укажите, что есть один незначительный тик между каждой парой основных тиков, вы закончите с отметками тика между вашими тиками. Ваш код будет выглядеть так:
var myAxis = d3.svg.axis()
.ticks(15)
.tickSubdivide(1)
.tickSize(0, 6, 0);
Обратите внимание, что вам нужно явно указать размер конца. Если вы предоставляете только два числа, они будут интерпретироваться как major
и end
, а minor
по умолчанию будет 0.
Здесь fiddle.
Ответ 4
Уже несколько хороших ответов, но только для добавления еще одного. Обратите внимание на использование text-anchor
.
Такая же идея: после вашего вызова выберите текст, переместите.
.call(xAxis)
.selectAll(".tick text")
.style("text-anchor", "start")
.attr("x", axisTextAdjust)
Ответ 5
Я часто делаю это, складывая несколько осей, каждый из которых имеет пользовательский .tickFormat()
.
Если я помещаю метки между датами, я часто буду делать что-то вроде этого:
@timeDaysAxisLabels = d3.svg.axis()
.scale(@timescale)
.orient('bottom')
.ticks(d3.time.hour.utc, 12) # I want ticks at noon, easiest to just get them ever 12 hours
.tickFormat((d) =>
# only draw labels at noon, between the date boundaries
if d.getUTCHours() == 12
# draw the label!
formatter = d3.time.format.utc('%a %d %b') # "Mon 12 Apr"
return formatter(d)
else
# not noon, don't draw anything
return null)
.tickSize(0)
.tickPadding(30)
Я также создаю отдельную ось без ярлыков вообще и ненулевое .tickSize()
, чтобы на самом деле рисовать тики, но этот блок над позициями помещает метки даты в центр столбца.
Ответ 6
svg.append("g")
.attr("class", "axis axis-years")
.attr("transform", "translate(0," + (height + 1) + ")")
.call(xAxis)
.selectAll("text")
.attr("x", "-1.8em")
.attr("y", ".00em")
.attr("transform", function (d) {
return "rotate(-90)"});
Ответ 7
При создании нижней оси X вместо создания только одной создайте две оси. Один будет там для вертикальных галочек, а другой для меток. Сдвиньте другую ось (одну только с текстами) на половину диапазона между двумя отметками (например, 12 часов, если она делится на целые дни).
Ответ 8
Возможно, вы захотите использовать D3FC, который имеет замену для компонента оси D3, поддерживающего эту функцию.
Вот пример, который заменяет ось D3 d3.axisBottom
, на эквивалент fc.axisBottom
:
const axis = fc.axisBottom(linear)
.tickCenterLabel(true);
tickCenterLabel
центрирует метки оси в соответствии с запросом.
Вот как выглядит ось с tickCenterLabel = false
:
![enter image description here]()
А вот с помощью tickCenterLabel = true
:
![enter image description here]()
Полное раскрытие - я поддерживаю и помогаю D3FC