Das Folgende ist eine andere Version von Mike Bostocks Lösung und inspiriert von @hughes 'Kommentar zu @ kashesandrs Antwort. Es macht einen einzelnen Rückruf am transitionEnde.
Gegeben eine dropFunktion ...
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);
}
... wir können d3so erweitern:
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;
}
Als JSFiddle .
Verwendung transition.end(callback[, delayIfEmpty[, arguments...]]):
transition.end(function() {
console.log("all done");
});
... oder mit einer optionalen Verzögerung, wenn transitionleer:
transition.end(function() {
console.log("all done");
}, 1000);
... oder mit optionalen callbackArgumenten:
transition.end(function(x) {
console.log("all done " + x);
}, 1000, "with callback arguments");
d3.transition.endwendet das übergebene callbackauch mit einem Leerzeichen an, transition wenn die Anzahl der Millisekunden angegeben ist oder wenn das zweite Argument wahr ist. Dadurch werden auch alle zusätzlichen Argumente an callback(und nur diese Argumente) weitergeleitet. Wichtig ist, dass dies nicht standardmäßig gilt, callbackwenn if transitionleer ist, was in einem solchen Fall wahrscheinlich eine sicherere Annahme ist.