A series of rectangles are plotted using d3.js
by fetching an array of 100 objects. Although the console.log(data)
shows that new data are being retrieved, the new data points do not seem to be appending any rectangles.
Was .enter().append()
used incorrectly?
function init() {
var width = 800,
height = 400,
margin = 50;
chart = d3.select('#chart')
.append('svg:svg')
.attr('width', width)
.attr('height', height);
}
function do_update() {
data = fetch_latest_top100();
console.log(data)
chart.selectAll('rect')
.data(data)
.enter()
.append('svg:rect')
.attr('x', function(d) { return x(d.x); })
.attr('y', function(d) { return y(d.y); })
.attr('height', function(d) { return d.value; })
.attr('width', function(d) { return 3 });
}
jsfiddle: http://jsfiddle.net/BU8cA/
The problem with your update method is that it ONLY handles new element, and does not update the existing elements to match their new data. After you have created the new rectangles with your enter() selection, you have to go back to your complete selection (new and changing rectangles) to set the attributes that are going to change.
The easiest way to do this is to store the selection in a variable at the point where you have applied the data function but before you call the enter method, like this:
var rects = chart.selectAll('rect')
.data(data);
rects.enter()
.append('svg:rect')
.attr('width', function(d) { return 3 });
// since the width is constant, you only need to set it once
rects.exit().remove(); //if the number of data points might shrink
rects.attr('x', function(d) { return x(d.x); })
.attr('y', function(d) { return y(d.y); })
.attr('height', function(d) { return d.value; });
//note that this now includes the rectangles created with enter()
//as well as the old ones you are resizing / repositioning
That should get the right data in, but you still have a layout problem (on the fiddle, anyway), in that your y values aren't being set correctly. The y value is the position of the top of the rectangle, so if you want bars that look like they are all sitting on the same line you need to adjust it based on the height of the bar. Mike Bostock's tutorial and demo here: http://bost.ocks.org/mike/bar/3/
Update for D3 version 4+
Elements appended to the "enter" selection are no longer automatically added to the main (update) selection. You now need to explicitly create a "merge" selection, by calling the merge
method on the "enter" selection:
var rects = chart.selectAll('rect')
.data(data);
rects.exit().remove(); //if the number of data points might shrink
rects.enter()
.append('svg:rect')
.attr('width', function(d) { return 3 }) // since the width is constant, you only need to set it once
.merge(rects)
//merge the newly added elements into the main selection
//of existing elements to update
.attr('x', function(d) { return x(d.x); })
.attr('y', function(d) { return y(d.y); })
.attr('height', function(d) { return d.value; });
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With