Je dois créer une méthode FadeOut (similaire à jQuery) en utilisant D3.js . Ce que je dois faire est de régler l'opacité sur 0 en utilisant transition()
.
d3.select("#myid").transition().style("opacity", "0");
Le problème est que j'ai besoin d'un rappel pour savoir quand la transition est terminée. Comment puis-je implémenter un rappel?
Vous voulez écouter l'événement "end" de la transition.
// d3 v5
d3.select("#myid").transition().style("opacity","0").on("end", myCallback);
// old way
d3.select("#myid").transition().style("opacity","0").each("end", myCallback);
De la documentation pour transition.each([type],listener)
:
Si le type est spécifié, ajoute un écouteur pour les événements de transition, prenant en charge les événements "début" et "fin". L'écouteur sera appelé pour chaque élément individuel de la transition, même si la transition a un retard et une durée constants. L'événement de démarrage peut être utilisé pour déclencher un changement instantané lorsque chaque élément commence à faire la transition. L'événement de fin peut être utilisé pour initier des transitions à plusieurs étapes en sélectionnant l'élément actuel,
this
, et en dérivant une nouvelle transition. Toutes les transitions créées lors de l'événement de fin hériteront de l'ID de transition actuel et ne remplaceront donc pas une transition plus récente précédemment planifiée.
Voir ce sujet du forum pour plus de détails.
Enfin, notez que si vous souhaitez simplement supprimer les éléments une fois leur transition terminée (une fois la transition terminée), vous pouvez utiliser transition.remove()
.
Mike Bostock's solution pour v3 avec une petite mise à jour:
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") });
Désormais, dans d3 v4.0, il existe une fonctionnalité permettant d’attacher explicitement des gestionnaires d’événements aux transitions:
https://github.com/d3/d3-transition#transition_on
Pour exécuter du code lorsqu'une transition est terminée, il vous suffit de:
d3.select("#myid").transition().style("opacity", "0").on("end", myCallback);
Une approche légèrement différente qui fonctionne également lorsqu'il y a de nombreuses transitions avec plusieurs éléments s'exécutant simultanément:
var transitions = 0;
d3.select("#myid").transition().style("opacity","0").each( "start", function() {
transitions++;
}).each( "end", function() {
if( --transitions === 0 ) {
callbackWhenAllIsDone();
}
});
Ce qui suit est une autre version de solution de Mike Bostock, inspirée du commentaire de @hughes à la réponse de @ kashesandr. Il effectue un seul rappel à la fin de transition
.
Étant donné une fonction drop
...
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);
}
... nous pouvons prolonger d3
comme suit:
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;
}
Utilisez transition.end(callback[, delayIfEmpty[, arguments...]])
:
transition.end(function() {
console.log("all done");
});
... ou avec un délai optionnel si transition
est vide:
transition.end(function() {
console.log("all done");
}, 1000);
... ou avec les arguments optionnels callback
:
transition.end(function(x) {
console.log("all done " + x);
}, 1000, "with callback arguments");
d3.transition.end
Appliquera le callback
passé même avec un transition
vide si le nombre de millisecondes est spécifié ou si le deuxième argument est la vérité. Cela transmettra également tous les arguments supplémentaires au callback
(et uniquement à ces arguments). Ce qui est important, c’est pas par défaut d’appliquer le callback
si transition
est vide, ce qui est probablement une hypothèse plus sûre dans un tel cas.
Mike Bostock solution amélioré de kashesandr + en passant des arguments à la fonction de rappel:
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");