web-dev-qa-db-ja.com

d3.js:軸の目盛りの間にテキストラベルを配置する

目盛りの間にテキストラベルを配置する簡単な方法はありますか?

目盛りの上にラベルがある私の時間軸は次のとおりです。
enter image description here

これらのラベルを次のように配置したいと思います。
enter image description here

36
oluckyman

私は Lars Kotthoffのアドバイスの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);
}

Update
ところで、ここにcalendarデモがあります:私は終わった: http://bl.ocks.org/oluckyman/6199145

enter image description here

48
oluckyman

これを行う簡単な(つまり組み込みの)方法はありませんが、それでも達成できます。いくつかのオプションがあります。最も簡単な方法は、おそらく tickFormat function を使用して、数字の前後に適切な数のスペースがある形式を指定することです。ただし、これはアプリケーションごとに手動で調整する必要があります。

または、描画後にラベル要素を選択し、それに応じてシフトする適切なtransform属性を追加できます。繰り返しますが、これは手動で調整する必要があります。

3番目のオプションは、目盛り用とラベル用の2つの異なる軸を持つことです。これは、目盛りを提供する軸にはラベルがなく、他の軸には目盛りがないという考え方です。ティック値を適切に設定する必要がありますが、少なくとも正しいオフセットを推測する必要はありません。

6
Lars Kotthoff

これを行うには、axis.tickSize(major[[,minor],end])および.tickSubdivide()を使用します。ティックはメジャーティックと並ぶように設定されていますが、これらのティックの高さを0に設定し、マイナーティックの高さを設定し、メジャーティックの各ペア間にマイナーティックが1つあることを指定すると、終了します目盛りの間に目盛りラベルを付けます。コードは次のようになります。

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

終了サイズを明示的に設定する必要があることに注意してください。 2つの数値のみを指定した場合、それらはmajorおよびendとして解釈され、minorはデフォルトで0になります。

フィドル

2
ckersch

すでにいくつかの良い返信が、もう1つ追加するだけです。 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()を作成しますが、このブロックは日付ラベルを「列」の中央に配置します。

0
Idan Gazit

D3FC の使用を検討することをお勧めします。この機能をサポートするD3軸コンポーネントのドロップイン置換があります。

D3FCの同等のd3.axisBottomをD3軸fc.axisBottomに置き換えた例を次に示します。

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

tickCenterLabelは、要求に応じて軸ラベルを中央揃えにします。

tickCenterLabel = falseを使用した場合の軸は次のとおりです。

enter image description here

そして、ここでtickCenterLabel = true

enter image description here

完全開示-私はD3FCのメンテナーであり貢献者です

0
ColinE
        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)"});
0
VINOTH KUMAR