Ich muss eine FadeOut-Methode (ähnlich wie jQuery) mit D3.js erstellen. Ich muss die Deckkraft mit transition()
auf 0 setzen.
d3.select("#myid").transition().style("opacity", "0");
Das Problem ist, dass ich einen Rückruf benötige, um festzustellen, wann der Übergang abgeschlossen ist. Wie kann ich einen Rückruf implementieren?
Sie möchten auf das "End" -Ereignis des Übergangs warten.
// d3 v5
d3.select("#myid").transition().style("opacity","0").on("end", myCallback);
// old way
d3.select("#myid").transition().style("opacity","0").each("end", myCallback);
Aus der Dokumentation zu transition.each([type],listener)
:
Wenn der Typ angegeben ist, wird ein Listener für Übergangsereignisse hinzugefügt, der sowohl Start- als auch Endereignisse unterstützt. Der Listener wird für jedes einzelne Element in der Überblendung aufgerufen, auch wenn die Überblendung eine konstante Verzögerung und Dauer aufweist. Das Startereignis kann verwendet werden, um eine sofortige Änderung auszulösen, wenn jedes Element mit dem Übergang beginnt. Mit dem Endereignis können mehrstufige Übergänge initiiert werden, indem das aktuelle Element
this
ausgewählt und ein neuer Übergang abgeleitet wird. Während des Endereignisses erstellte Übergänge erben die aktuelle Übergangs-ID und überschreiben daher keinen zuvor geplanten neueren Übergang.
Siehe dieser Forenthread zum Thema für weitere Details.
Beachten Sie schließlich, dass Sie transition.remove()
verwenden können, wenn Sie die Elemente erst nach dem Ausblenden (nach Abschluss des Übergangs) entfernen möchten.
Mike Bostocks Lösung für v3 mit einem kleinen Update:
function endall(transition, callback) {
if (typeof callback !== "function") throw new Error("Wrong callback in endall");
if (transition.size() === 0) { callback() }
var n = 0;
transition
.each(function() { ++n; })
.each("end", function() { if (!--n) callback.apply(this, arguments); });
}
d3.selectAll("g").transition().call(endall, function() { console.log("all done") });
In d3 v4.0 gibt es jetzt eine Funktion zum expliziten Anhängen von Ereignishandlern an Übergänge:
https://github.com/d3/d3-transition#transition_on
Um Code nach Abschluss eines Übergangs auszuführen, müssen Sie lediglich Folgendes tun:
d3.select("#myid").transition().style("opacity", "0").on("end", myCallback);
Ein etwas anderer Ansatz, der auch funktioniert, wenn viele Übergänge mit vielen Elementen gleichzeitig ausgeführt werden:
var transitions = 0;
d3.select("#myid").transition().style("opacity","0").each( "start", function() {
transitions++;
}).each( "end", function() {
if( --transitions === 0 ) {
callbackWhenAllIsDone();
}
});
Das Folgende ist eine andere Version von Mike Bostocks Lösung und inspiriert von @ hughes 'Kommentar zu @ kashesandrs Antwort. Es wird ein einzelner Rückruf nach dem Ende von transition
durchgeführt.
Eine drop
-Funktion gegeben ...
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 d3
folgendermaßen 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;
}
Benutze transition.end(callback[, delayIfEmpty[, arguments...]])
:
transition.end(function() {
console.log("all done");
});
... oder mit einer optionalen Verzögerung, wenn transition
leer ist:
transition.end(function() {
console.log("all done");
}, 1000);
... oder mit optionalen callback
Argumenten:
transition.end(function(x) {
console.log("all done " + x);
}, 1000, "with callback arguments");
d3.transition.end
Wird den übergebenen callback
auch bei einem leeren transition
anwenden if die Anzahl der Millisekunden wird angegeben oder if Das zweite Argument ist wahr. Dadurch werden auch alle zusätzlichen Argumente an callback
weitergeleitet (und nur diese Argumente). Wichtig ist, dass dies nicht standardmäßig das callback
anwendet, wenn transition
leer ist, was in einem solchen Fall wahrscheinlich eine sicherere Annahme ist.
Mike Bostocks Lösung wurde durch kashesandr + Überholen verbessert Argumente zur Rückruffunktion:
function d3_transition_endall(transition, callback, arguments) {
if (!callback) callback = function(){};
if (transition.size() === 0) {
callback(arguments);
}
var n = 0;
transition
.each(function() {
++n;
})
.each("end", function() {
if (!--n) callback.apply(this, arguments);
});
}
function callback_function(arguments) {
console.log("all done");
console.log(arguments);
}
d3.selectAll("g").transition()
.call(d3_transition_endall, callback_function, "some arguments");