Подтвердить что ты не робот

D3.js: выравнивание текстовых меток между тиками по оси

Есть ли простой способ выровнять текстовые метки между тиками?

Вот моя временная ось с надписями над тиками:
enter image description here

Я хотел бы разместить эти ярлыки, как здесь:
enter image description here

4b9b3361

Ответ 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