Sure. Here are two ways.
First, you could use an explicit delay, which you then compute using selection.empty to skip empty transitions. (This is only a minor modification of what you have already.)
var div = d3.select("body").selectAll("div")
.data(["enter", "update"], function(d) { return d || this.textContent; });
// 2. update
div.transition()
.duration(duration)
.delay(!div.exit().empty() * duration)
.style("background", "orange");
// 3. enter
div.enter().append("div")
.text(function(d) { return d; })
.style("opacity", 0)
.transition()
.duration(duration)
.delay((!div.exit().empty() + !div.enter().empty()) * duration)
.style("background", "green")
.style("opacity", 1);
// 1. exit
div.exit()
.style("background", "red")
.transition()
.duration(duration)
.style("opacity", 0)
.remove();
http://bl.ocks.org/mbostock/5779682
One tricky thing here is that you have to create the transition on the updating elements before you create the transition on the entering elements; that’s because enter.append merges entering elements into the update selection, and you want to keep them separate; see the Update-only Transition example for details.
Alternatively, you could use transition.transition to chain transitions, and transition.each to apply these chained transitions to existing selections. Within the context of transition.each, selection.transition inherits the existing transition rather than creating a new one.
var div = d3.select("body").selectAll("div")
.data(["enter", "update"], function(d) { return d || this.textContent; });
// 1. exit
var exitTransition = d3.transition().duration(750).each(function() {
div.exit()
.style("background", "red")
.transition()
.style("opacity", 0)
.remove();
});
// 2. update
var updateTransition = exitTransition.transition().each(function() {
div.transition()
.style("background", "orange");
});
// 3. enter
var enterTransition = updateTransition.transition().each(function() {
div.enter().append("div")
.text(function(d) { return d; })
.style("opacity", 0)
.transition()
.style("background", "green")
.style("opacity", 1);
});
http://bl.ocks.org/mbostock/5779690
I suppose the latter is a bit more idiomatic, although using transition.each to apply transitions to selections (rather than derive transitions with default parameters) isn’t a widely-known feature.
与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…