I'm not sure I understand exactly what you're saying, but the usual 'd3' way is quite simple.
First, the question is when is the moment that a graph is 'rendered'.
Unless you do some very fancy stuff, the data loading + graph generating code has a structure similar to this:
d3.json("data-url.json", function(json) {
// data has been loaded and now we generate the SVG DOM content:
var selection = d3.selectAll("<some base node>")
.data(json);
selection.exit().remove();
selection.enter().append("svg nodes").blahblah();
selection.update_existing_svg_nodes_blahblah();
// <pling!>
});
where d3.json is one of many ways to load data from a server and the selection.xyz... code in the callback handler is updating/generating the DOM to visualize the data.
To answer the question "when is the render completed?": when the JavaScript execution reaches the line "<pling!>" the DOM construction will be complete and the JavaScript run will terminate immediately after, so this is the point where the content gets rendered (when JS execution terminates, the browser will render the content, as usual).
The above applies to plain vanilla d3 coding; all the (basic) examples use this behavioral pattern.
Which leads us to the question about animating and 'chaining' animation.
You don't need a 'done' event for data loaded because the callback function you specify for d3.json, d3.csv, etc. _is_ the 'done' handler, at least for the 'data load complete'. Given the above structure, basic visualization will then construct the corresponding DOM at once and you're ready to 'transition' your d3.selection in order to animate it.
So what to do when you want to 'animate' the data visualization update on data load/update from the server?
That's where you go and use d3.transition to tell d3 to 'transition' to the specified target (
https://github.com/mbostock/d3/wiki/Transitions -- note the first paragraph so you must enter().append("<svg node>").transition().attr_blabla() when you add DOM nodes and wish to animate these; it may be handy to append() them and immediately set their opacity or other property to zero, so the transition can 'fade them in'.
Think of transitions as 'animating settings from value a to b': that way it's immediately clear that you must create all DOM nodes you want to end up with at the end of a transition beforehand, so transitions can animate the opacity, position, or other attribute(s) to make them visible (or have them disappear; a 'fade-out' statement like .exit().transition().attr("opacity", 1e-6).remove() is used quite often, where the opacity is dialed down to 1e-6 instead of plain zero(0) to circumvent a tween bug/issue in some browsers. This also indicates that any nodes that are to be gone once the animation is complete, are simply remove()d once the transition completes.
BTW: If you seek more case specific responses from mailing list members, offering a case sample as a gist (and
http://bl.ocks.org/ ) is strongly recommended.
Met vriendelijke groeten / Best regards,