D3.js Barchart:让x轴标签与条形对齐,并稍微旋转它们

时间:2013-12-31 14:42:00

标签: javascript charts d3.js

我有一个d3垂直条形图,我正在尝试正确定位x轴标签。它几乎 那里,但并不完全。标签最终偏离了酒吧。我还想稍微旋转标签,以便在需要时可以容纳更大的图形。

这是我的咖啡图表(那里有一些Backbone Marionette):

  buildTimeline: ->
    width = @ui.chartWrap.innerWidth()
    height = @ui.chartWrap.height()
    dataLength = @data.values.length

    x = d3.scale.ordinal()
      .rangeRoundBands([0, width], 0.1)
    y = d3.scale.linear()
      .range([height, 0])
    x.domain @data.values.map (d) ->
      d.x
    y.domain [0, d3.max(@data.values, (d) ->
      d.y
    )]
    xAxis = d3.svg.axis()
      .scale(x)
      .orient("bottom")

    svg = d3.select(@ui.chartWrap[0]).append('svg')
        .attr('width', width)
        .attr('height', height)
        .append('g')
        .attr('transform', '0,0')

    svg.append("g")
      .attr('id', 'timeline-labels')
      .attr("transform", "translate(0,#{height-20})")
      .call(xAxis)

    # Bars
    svg.append('g')
      .attr('id', 'timeline-bars')
      .selectAll(".bar")
      .data(@data.values)
      .enter().append("rect")
      .attr("class", "bar")
      .attr("x", (d) ->
        x(d.x)
      )
      .attr("width", 25)
      .attr("y", (d) ->
        y(d.y) - 30
      )
      .attr("height", (d) =>
        height - y(d.y)
      ).attr("data-date", (d) =>
        d.x
      ).attr("data-count", (d) =>
        d.y
      )

然后这是图表的示例JSON:

{
    "key": "Documents",
    "values": [
        {
            "x": "1980",
            "y": 1752
        },
        {
            "x": "1981",
            "y": 0
        },
        {
            "x": "1982",
            "y": 0
        },
        {
            "x": "1983",
            "y": 0
        },
        {
            "x": "1984",
            "y": 0
        },
        {
            "x": "1985",
            "y": 0
        },
    ],
    "type": "year"
}

最终图表几乎就在那里,但现在所有标签都堆叠在一个栏下:D3 Chart

1 个答案:

答案 0 :(得分:0)

感谢@ lars-kothoff。解决方案最终证明是使用时间尺度:

  buildTimeline: ->
    width = @ui.chartWrap.innerWidth()
    height = @ui.chartWrap.height()
    dataLength = @data.values.length
    x = d3.time.scale()
      .domain(
        [
          new Date "#{@data.values[0].x}-1-1"
          new Date("#{@data.values[dataLength - 1].x}-1-1")
        ]
      ).rangeRound [0, width]

    y = d3.scale.linear()
      .domain(
        [
          0
          d3.max(@data.values, (d) ->
            d.y
          )
        ]
      ).range [height, 0]

    xAxis = d3.svg.axis()
      .scale(x)
      .orient('bottom')
      .ticks(d3.time.years, 1)
      .tickFormat(d3.time.format('%Y'))
      .tickSize(0)
      .tickPadding(8)

    yAxis = d3.svg.axis()
      .scale(y)
      .orient('left')
      .tickPadding(8)

    svg = d3.select(@ui.chartWrap[0]).append('svg')
        .attr('width', width)
        .attr('height', height)
        .append('g')
        .attr('transform', '0,0')

    # Bars
    svg.append('g')
      .attr('id', 'timeline-bars')
      .selectAll(".bar")
      .data(@data.values)
      .enter().append("rect")
      .attr("class", "bar")
      .attr("x", (d) ->
        x(new Date "#{d.x}-1-1")
      )
      .attr("width", 25)
      .attr("y", (d) ->
        y(d.y) - 30
      )
      .attr("height", (d) =>
        height - y(d.y)
      ).attr("data-date", (d) =>
        d.x
      ).attr("data-count", (d) =>
        d.y
      )

    svg.append("g")
      .attr('id', 'timeline-labels')
      .attr('class', 'x axis')
      .attr("transform", "translate(0,#{height-20})")
      .call(xAxis)

    svg.append("g")
      .attr('class', 'y axis')
      .call(yAxis)