La siguiente es otra versión de la solución de Mike Bostock e inspirada en el comentario de @hughes a la respuesta de @ kashesandr. Hace una única llamada atransition final.
Dada una dropfunción ...
function drop(n, args, callback) {
for (var i = 0; i < args.length - n; ++i) args[i] = args[i + n];
args.length = args.length - n;
callback.apply(this, args);
}
... podemos extendernos d3así:
d3.transition.prototype.end = function(callback, delayIfEmpty) {
var f = callback,
delay = delayIfEmpty,
transition = this;
drop(2, arguments, function() {
var args = arguments;
if (!transition.size() && (delay || delay === 0)) { // if empty
d3.timer(function() {
f.apply(transition, args);
return true;
}, typeof(delay) === "number" ? delay : 0);
} else { // else Mike Bostock's routine
var n = 0;
transition.each(function() { ++n; })
.each("end", function() {
if (!--n) f.apply(transition, args);
});
}
});
return transition;
}
Como JSFiddle .
Utilizar transition.end(callback[, delayIfEmpty[, arguments...]]):
transition.end(function() {
console.log("all done");
});
... o con un retraso opcional si transitionestá vacío:
transition.end(function() {
console.log("all done");
}, 1000);
... o con callbackargumentos opcionales :
transition.end(function(x) {
console.log("all done " + x);
}, 1000, "with callback arguments");
d3.transition.endaplicará el pasado callbackincluso con un vacío transition si se especifica el número de milisegundos o si el segundo argumento es verdadero. Esto también enviará cualquier argumento adicional al callback(y solo esos argumentos). Es importante destacar que esto no aplicará de forma predeterminadacallback si transitionestá vacío, lo que probablemente sea una suposición más segura en tal caso.