我有以下数据集:
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),如下所示:
我的问题是,目前,我正在使用x尺度,图形看起来像这样 - 基本上条形图位于错误的位置,最后一个条形图从图表上掉下来:
这是一个包含完整代码和工作图的JSFiddle:http://jsfiddle.net/aWJtJ/4/
为了达到我想要的效果,我认为我需要修改x-scale,以便在第一个数据点之前和最后一个数据点之后有额外的宽度,这样条形码就是所有都向左移动了每个条的宽度的一半。
任何人都可以帮我弄清楚我需要用x-scale做什么?
我已经尝试在域中添加一个额外的月份 - 这会阻止最后一个栏从图表的末尾掉落,但它也会添加一个我不想要的额外刻度,并且它不会修复该位置线图和刻度线。
如果可能的话,我想继续x轴的时间尺度,而不是顺序尺度,因为我想使用D3的基于时间的聪明的刻度格式器和日期解析器,例如: xAxis.ticks(d3.time.weeks, 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
语句根本没有被修改过。