In this problem, the transitions are clearly the trickiest part, so I prefered to go from the simple bar example you provided and go to the stacked bar chart using Mike Bostock's example.
The principal problem with the stacked implementation you provide is that the information is "reversed" as you would want each bar to be in a different element of the data array, this way you can identify your data by its time stamp.
So, first, let's define some data with an array of values for each element:
function next () {
return {
time: ++t,
value: d3.range(3).map(getRand)
};
}
Then, inside of the redraw()
function:
First format the data for the bar stacks:
customData = data.map(function(d){ y0=0 return {value:d.value.map(function(d){return {y0:y0, y1: y0+=d}}), time:d.time} })
Then create the group for each stack of bar
var state = graph.selectAll(".g") .data(customData, function(d) { return d.time; }); var stateEnter = state.enter().append("g") .attr("class", "g") .attr("transform", function(d) { return "translate(" + x(d.time+1) + ",0)"; });
Then, add the stack of bars of the group:
stateEnter.selectAll("rect") .data(function(d) { return d.value; }) .enter().append("rect") .attr("width", barWidth) .attr("y", function(d) {return y(d.y1); }) .attr("height", function(d) { return y(d.y0) - y(d.y1); }) .attr("class", "bar") .style("fill", function(d,i) { return color(i); });
Move every bar group to update the x values:
state.transition().duration(1000) .attr("transform", function(d) {console.log(d); return "translate(" + x(d.time) + ",0)"; });
Remove old values
state.exit() .attr("transform", function(d) {return "translate(" + x(d.time) + ",0)";}) .remove()
PS: Next time, please provide jsFiddles so we don't have to go to the source code of your page to provide a solution. Also, try to minimize as much as possible the code of your example (remove axis, useless parsing etc) so we can concentrate on what is wrong. Also, in the process you will often find the problem by yourself as you isolate it.