d3.js:在轴上的刻度之间对齐文本标签

时间:2013-07-09 09:21:26

标签: d3.js calendar label axis-labels

是否有一种简单的方法可以在刻度线之间对齐文本标签?

这是我的时间轴,标签上方有标签:
enter image description here

我想把这些标签放在这里:
enter image description here

7 个答案:

答案 0 :(得分:48)

我最终得到了Lars Kotthoff's advices之一。

每当我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

答案 1 :(得分:6)

没有简单的(即内置)方式,但你仍然可以实现它。有几个选择。最直接的可能是使用tickFormat function来指定在数字前面/后面有适当数量空格的格式。这需要针对每个应用程序进行手动调整。

或者,您可以在绘制标签元素后选择它们,并添加适当的transform属性,以相应地移动它们。同样,这必须手动调整。

你的第三个选择是有两个不同的轴,一个用于刻度线,另一个用于标签。这个想法是提供刻度线的轴没有标签而另一个没有刻度线。您需要适当地设置刻度值,但至少您不必猜测正确的偏移量。

答案 2 :(得分:2)

您可以使用axis.tickSize(major[[,minor],end]).tickSubdivide()来完成此操作。您的刻度线设置为与主刻度线对齐,但如果您将这些刻度线的高度设置为0,并为次刻度设置一些高度,并指定每对主刻度线之间有一个小刻度线,则您将结束你的刻度线之间有刻度标签。你的代码看起来像这样:

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

请注意,您需要明确设置结束大小。如果您只提供两个号码,则会将其解释为majorend,而minor将默认为0。

这是fiddle.

答案 3 :(得分:1)

已经有一些很好的回复,但只是添加一个。请注意text-anchor的使用。

同样的想法:通话结束后,选择文字,重新定位。

.call(xAxis)                
.selectAll(".tick text")
.style("text-anchor", "start")
.attr("x", axisTextAdjust)

答案 4 :(得分: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(),但是上面的这个块将日期标签定位在“列”的中心。

答案 5 :(得分:0)

        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)"});

答案 6 :(得分:0)

您可能要考虑使用D3FC,它可以替代支持该功能的D3轴组件。

下面是一个示例,它用D3轴d3.axisBottom代替等效的D3FC fc.axisBottom

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

tickCenterLabel根据要求将轴标签居中。

这是tickCenterLabel = false轴的样子:

enter image description here

这里是tickCenterLabel = true

enter image description here

全面披露-我是D3FC的维护者和贡献者