D3: How to change data on an existing histogram?

I have successfully created my initial histogram. Now I want to add more bars to the existing chart, using transitions to have a nice user interface.

Here is my code:

var data = [23, 85, 67, 38, 70]; //dummy, normally much more labellist = ['label1','label2','label3','label4','label5']; var w = 815, h = 500, labelpad = 165, x = d3.scale.linear().domain([0, 100]).range([0, w]), y = d3.scale.ordinal().domain(d3.range(data.length)).rangeBands([0, h], .2); mySvg = d3.select("#chart") .append("svg"); vis = mySvg.attr("width", w + 40) .attr("height", h + 20) .append("svg:g") .attr("transform", "translate(20,0)"); bars = vis.selectAll("g.bar") .data(data) .enter().append("svg:g") .attr("class", "bar") .attr("transform", function(d, i) { return "translate(" + labelpad + "," + y(i) + ")"; }) bars.append("svg:rect") .transition() .duration(500) .attr("width", x) .attr("height", y.rangeBand()) ; var rules = vis.selectAll("g.rule") .data(x.ticks(10)) .enter().append("svg:g") .attr("class", "rule") .attr("transform", function(d) { return "translate(" + x(d) + ", 0)"; }); rules.append("svg:line") .attr("y1", h) .attr("y2", h + 6) .attr("x1", labelpad) .attr("x2", labelpad) .attr("stroke", "black"); rules.append("svg:line") .attr("y1", 0) .attr("y2", h) .attr("x1", labelpad) .attr("x2", labelpad) .attr("stroke", "white") .attr("stroke-opacity", .3); 

How can I programmatically modify data to add and remove other bars and allow existing ones to slide up / down?

+4
source share
1 answer

You need to assign some form of key for these bars so that d3 can identify those that existed in the previous set. By default, indexing is used, and this may be what you want.

Regarding the transitions, you want to change your code to something like this:

 bars = vis.selectAll("g.bar") .data(data); bars.enter().append("svg:g") .attr("class", "bar") .append("svg:rect"). bars.transition().duration(500) .attr("transform", function(d, i) { return "translate(" + labelpad + "," + y(i) + ")"; }) .selectAll("svg:rect") .attr("width", x) .attr("height", y.rangeBand()) ; bars.exit().transition().duration(500) .selectAll("svg:rect") .attr("height", 0) .remove(); 

The "enter ()" function is best used to instantly create a structure. Then use the original selection object (bars) to apply the new data to all elements.

You also probably want to remove obsolete bars. Here I resized them to 0 and then deleted them, but you can tinker with it to get the desired effect.

+6
source

All Articles