Есть ли простой способ выровнять текстовые метки между тиками?
Вот моя временная ось с надписями над тиками:
Я хотел бы разместить эти ярлыки, как здесь:
Есть ли простой способ выровнять текстовые метки между тиками?
Вот моя временная ось с надписями над тиками:
Я хотел бы разместить эти ярлыки, как здесь:
Я закончил с одним из советов Ларса Коттоффа.
Каждый раз, когда я 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
Нет простого (то есть встроенного) способа сделать это, но вы все равно можете достичь этого. Есть несколько вариантов. Наиболее простой tickFormat
- использовать функцию tickFormat
для указания формата с подходящим количеством пробелов перед/после чисел. Это должно быть настроено вручную для каждого приложения, хотя.
В качестве альтернативы, вы можете выбрать элементы метки после того, как они были нарисованы, и добавить подходящий атрибут transform
который соответствующим образом смещает их. Опять же, это должно быть настроено вручную.
Ваш третий вариант - иметь две разные оси, одну для галочек и одну для меток. Идея состоит в том, что ось, которая обеспечивает метки, не имеет меток, а другая не имеет меток. Вам нужно было бы правильно установить значения тиков, но, по крайней мере, вам не нужно угадывать правильное смещение.
Вы можете сделать это, используя 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.
Уже несколько хороших ответов, но только для добавления еще одного. Обратите внимание на использование text-anchor
.
Такая же идея: после вашего вызова выберите текст, переместите.
.call(xAxis)
.selectAll(".tick text")
.style("text-anchor", "start")
.attr("x", axisTextAdjust)
Я часто делаю это, складывая несколько осей, каждый из которых имеет пользовательский .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()
, чтобы на самом деле рисовать тики, но этот блок над позициями помещает метки даты в центр столбца.
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)"});
При создании нижней оси X вместо создания только одной создайте две оси. Один будет там для вертикальных галочек, а другой для меток. Сдвиньте другую ось (одну только с текстами) на половину диапазона между двумя отметками (например, 12 часов, если она делится на целые дни).
Возможно, вы захотите использовать D3FC, который имеет замену для компонента оси D3, поддерживающего эту функцию.
Вот пример, который заменяет ось D3 d3.axisBottom
, на эквивалент fc.axisBottom
:
const axis = fc.axisBottom(linear)
.tickCenterLabel(true);
tickCenterLabel
центрирует метки оси в соответствии с запросом.
Вот как выглядит ось с tickCenterLabel = false
:
А вот с помощью tickCenterLabel = true
:
Полное раскрытие - я поддерживаю и помогаю D3FC