d3.js: выравнивать текстовые метки между галочками на оси

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

Вот моя временная ось с метками над галочками:

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

6 ответов

Решение

Я закончил с одним из советов Ларса Коттоффа.

Каждый раз, когда я 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 функция для указания формата с подходящим количеством пробелов перед / после чисел. Это должно быть настроено вручную для каждого приложения, хотя.

Кроме того, вы можете выбрать элементы метки после того, как они были нарисованы и добавить подходящий transform атрибут, который сдвигает их соответственно. Опять же, это должно быть настроено вручную.

Третий вариант - две разные оси, одна для галочек и одна для меток. Идея состоит в том, что ось, которая обеспечивает метки, не имеет меток, а другая не имеет меток. Вам нужно было бы правильно установить значения тиков, но, по крайней мере, вам не нужно угадывать правильное смещение.

Возможно, вы захотите рассмотреть возможность использования D3FC, который имеет замену компонента оси D3, поддерживающего эту функцию.

Вот пример, который заменяет ось D3 d3.axisBottom, для эквивалента D3FC fc.axisBottom:

const axis = fc.axisBottom(linear)
  .tickCenterLabel(true);

В tickCenterLabel центрирует метки осей по запросу.

Вот как выглядит ось с tickCenterLabel = false:

А здесь с tickCenterLabel = true:

Полное раскрытие информации - я сопровождаю и участвую в D3FC

Вы можете сделать это с помощью axis.tickSize(major[[,minor],end]) а также .tickSubdivide(), Ваши тики настроены на соответствие основным тикам, но если вы установите высоту этих тиков на 0, а также установите некоторую высоту для небольших тиков и укажите, что между каждой парой основных тиков есть один второстепенный тик, вы закончите с галочкой между вашими галочками. Ваш код будет выглядеть так:

var myAxis = d3.svg.axis()
    .ticks(15)
    .tickSubdivide(1)
    .tickSize(0, 6, 0);

Обратите внимание, что вам нужно явно установить конечный размер. Если вы предоставите только два числа, они будут интерпретированы как major а также end а также minor по умолчанию будет 0.

Вот скрипка

Я часто делаю это, складывая несколько осей, каждая со своим .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() на самом деле рисовать галочки, но этот блок выше позиционирует метки даты в центре "столбца".

Уже несколько хороших ответов, но только чтобы добавить еще один. Обратите внимание на использование text-anchor,

Та же идея: после звонка выделите текст, измените положение.

.call(xAxis)                
.selectAll(".tick text")
.style("text-anchor", "start")
.attr("x", axisTextAdjust)
        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)"});
Другие вопросы по тегам