D3.js:计算条形图的x轴时标?

时间:2013-09-17 15:26:32

标签: d3.js

我有以下数据集:

var data = [
  {
    "air_used": 0.660985, 
    "datestr": "2012-12-01 00:00:00", 
    "energy_used": 0.106402
  }, 
  {
    "air_used": 0.824746, 
    "datestr": "2013-01-01 00:00:00", 
    "energy_used": 0.250462
  } ...
]

我想绘制一个条形图(对于air_used)和折线图(对于energy_used),如下所示:

enter image description here

我的问题是,目前,我正在使用x尺度,图形看起来像这样 - 基本上条形图位于错误的位置,最后一个条形图从图表上掉下来:

enter image description here

这是一个包含完整代码和工作图的JSFiddle:http://jsfiddle.net/aWJtJ/4/

为了达到我想要的效果,我认为我需要修改x-scale,以便在第一个数据点之前和最后一个数据点之后有额外的宽度,这样条形码就是所有都向左移动了每个条的宽度的一半。

任何人都可以帮我弄清楚我需要用x-scale做什么?

我已经尝试在域中添加一个额外的月份 - 这会阻止最后一个栏从图表的末尾掉落,但它也会添加一个我不想要的额外刻度,并且它不会修复该位置线图和刻度线。

如果可能的话,我想继续x轴的时间尺度,而不是顺序尺度,因为我想使用D3的基于时间的聪明的刻度格式器和日期解析器,例如: xAxis.ticks(d3.time.weeks, 2)

2 个答案:

答案 0 :(得分:4)

将您的域扩展为数据的实际范围+1和1个月。这将填充图表中任意一侧的额外月份,然后更新条形宽度以将数据元素的数量加2。

var barRawWidth = width / (data.length + 2);

看到这个小提琴:http://jsfiddle.net/reblace/aWJtJ/6/

如果你想隐藏下边界和上边界月份,你可以这样修改它:http://jsfiddle.net/reblace/aWJtJ/7/只需加上和减去20天而不是整整一个月,但可能有更优雅的方法来做到这一点

var xExtent = d3.extent(data, function(d) { return d.date; });
var nxExtent = [d3.time.day.offset(xExtent[0], -20), d3.time.day.offset(xExtent[1], 20)];
x.domain(nxExtent);

答案 1 :(得分:0)

正如评论中所指出的,我认为最好的方法是使用d3.scale.ordinal。请注意,使用它并不会阻止您使用d3.time解析器,但您需要考虑条形宽度以使线条与条形对齐。

这里有一个示例解决方案: http://jsfiddle.net/jcollado/N8tuR/

上述解决方案的相关代码如下:

// Map data set to dates to provide the whole domain information
var x = d3.scale.ordinal()
    .domain(data.map(function(d) {
        return d.date;
    }))
    .rangeRoundBands([0, width], 0.1);

...

// Use x.rangeBand() to align line with bars
var line = d3.svg.line()
    .x(function(d) { return x(d.date) + x.rangeBand() / 2; })
    .y(function(d) { return y(d.energy_used); });

...

// Use x.rangeBand() to set bar width
bars.enter().append("rect")
    .attr("class", "air_used")
    .attr("width", x.rangeBand())
    ...

请注意,在创建x比例时,日期解析代码已向上移动以使d.date可用。除此之外,d3.time语句根本没有被修改过。