D3JS 在时间尺度上堆叠条形图
D3JS stacked bar-chart over a timescale
我的 JSON 看起来像这样(有一些额外的记录,为了简洁我没有包括在内)
[{"name":"Jim","category":"TechSupport","month":"8",year:"2012","Date":"2012-08-01T04:00:00.000Z", "TechSupport":2,"Management":0,"Sales":0},
{"name":"Jim","category":"Management","month":"8",year:"2012","Date":"2012-08-01T04:00:00.000Z", "TechSupport":0,"Management":3,"Sales":0}]
我的堆栈看起来像这样
var stack = d3.stack().keys(["TechSupport", "Management", "Sales"])
var series = stack(data)
我的堆栈结果看起来像 [[0,2],[0,0]],[[2,2],[3,3]],[[1,1],[3,3]]
我在时间刻度上显示条形图的代码如下所示
var groups = mainChart.selectAll("g")
.data(series)
.append("g")
groups.selectAll("rect")
.attr("id","bar")
.attr("fill", function(d){return colors(d.data.category)})
.attr("x", function(d){return xScale(d.data.Date);}}
.attr("y", function(d){return yScale(d[1]);})
.attr("width", 20)
.attr("height" return yScale(d[0]) - yScale(d[1])})
我可以让所有内容都沿着时间轴正确显示,除非我有日期相同的项目,但这些项目没有堆叠,我不确定为什么?
正在准备数据集 - forEach()
在您的 forEach 函数中,我更改了两个小错误。
将技术s支持更改为技术S支持,就像我之前提到的那样:
else if(d.category == 'Techsupport')
并且通过 cattotal 的管理,我添加了 +:
d.Management = +d.cattotal;
正在准备数据集 - reduce()
您有一个 JSON,其中包含多个基于原始数据集的对象。必须根据唯一的日期条目减少此数据集。对象值应该合并。然后你有一个很好的堆栈功能JSON。
这可以通过多种方式实现。我使用如下所示的 reduce() 函数:
var dataset = [];
data.reduce(function(res,obj){
var key = obj.Date;
if (res[key]){
res[key].Sales +=obj.Sales;
res[key].Techsupport +=obj.Techsupport;
res[key].Management +=obj.Management;
} else {
dataset.push(o);
res[key] = obj;
}
return res;
}, {});
数据集包含为堆栈函数准备好的数据。但是,我不想在您的整个代码中将 data 替换为 dataset,因此我轻松更新了 data:
data = dataset;
当然你可以自由选择。
响应式y轴:
y 轴必须自动适应堆叠条,所以我将 yMax 更改为:
var yMax = d3.max(series[series.length - 1], function(d) { return d[1]; });
正在更新绘制堆叠条和工具提示
最后,我通过调整填充属性更新了堆叠条。我为您的主图表和导航图表更改了它。
.attr("fill", function(d){ return colors(d3.select(this.parentNode).datum().key)})
对于工具提示,我更新了 Key 和 Total 值:
div.html("Date: " +d.data.Date + "<br>" + "Category: " + d3.select(this.parentNode).datum().key + "<br>" + "Total:" + (d[1]-d[0]))
在这个 fiddle 中,您可以找到一个工作示例。
我的 JSON 看起来像这样(有一些额外的记录,为了简洁我没有包括在内)
[{"name":"Jim","category":"TechSupport","month":"8",year:"2012","Date":"2012-08-01T04:00:00.000Z", "TechSupport":2,"Management":0,"Sales":0},
{"name":"Jim","category":"Management","month":"8",year:"2012","Date":"2012-08-01T04:00:00.000Z", "TechSupport":0,"Management":3,"Sales":0}]
我的堆栈看起来像这样
var stack = d3.stack().keys(["TechSupport", "Management", "Sales"])
var series = stack(data)
我的堆栈结果看起来像 [[0,2],[0,0]],[[2,2],[3,3]],[[1,1],[3,3]]
我在时间刻度上显示条形图的代码如下所示
var groups = mainChart.selectAll("g")
.data(series)
.append("g")
groups.selectAll("rect")
.attr("id","bar")
.attr("fill", function(d){return colors(d.data.category)})
.attr("x", function(d){return xScale(d.data.Date);}}
.attr("y", function(d){return yScale(d[1]);})
.attr("width", 20)
.attr("height" return yScale(d[0]) - yScale(d[1])})
我可以让所有内容都沿着时间轴正确显示,除非我有日期相同的项目,但这些项目没有堆叠,我不确定为什么?
正在准备数据集 - forEach()
在您的 forEach 函数中,我更改了两个小错误。
将技术s支持更改为技术S支持,就像我之前提到的那样:
else if(d.category == 'Techsupport')
并且通过 cattotal 的管理,我添加了 +:
d.Management = +d.cattotal;
正在准备数据集 - reduce()
您有一个 JSON,其中包含多个基于原始数据集的对象。必须根据唯一的日期条目减少此数据集。对象值应该合并。然后你有一个很好的堆栈功能JSON。
这可以通过多种方式实现。我使用如下所示的 reduce() 函数:
var dataset = [];
data.reduce(function(res,obj){
var key = obj.Date;
if (res[key]){
res[key].Sales +=obj.Sales;
res[key].Techsupport +=obj.Techsupport;
res[key].Management +=obj.Management;
} else {
dataset.push(o);
res[key] = obj;
}
return res;
}, {});
数据集包含为堆栈函数准备好的数据。但是,我不想在您的整个代码中将 data 替换为 dataset,因此我轻松更新了 data:
data = dataset;
当然你可以自由选择。
响应式y轴:
y 轴必须自动适应堆叠条,所以我将 yMax 更改为:
var yMax = d3.max(series[series.length - 1], function(d) { return d[1]; });
正在更新绘制堆叠条和工具提示
最后,我通过调整填充属性更新了堆叠条。我为您的主图表和导航图表更改了它。
.attr("fill", function(d){ return colors(d3.select(this.parentNode).datum().key)})
对于工具提示,我更新了 Key 和 Total 值:
div.html("Date: " +d.data.Date + "<br>" + "Category: " + d3.select(this.parentNode).datum().key + "<br>" + "Total:" + (d[1]-d[0]))
在这个 fiddle 中,您可以找到一个工作示例。