2 votes

Interrompre les transitions de défilement en D3.js

Je suis en train d'utiliser la bibliothèque javascript scrollama pour écrire un article "scrollytelling" qui implique la transition des graphiques D3 dans et hors de la vue lorsque l'utilisateur fait défiler. Cela fonctionne principalement, mais les graphiques s'accumulent les uns sur les autres si je fais défiler trop rapidement.

Voici un jsfiddle basé sur cet exemple par l'auteur de scrollama. Dans mon exemple, les points colorés devraient apparaître un par un. Si vous faites défiler rapidement jusqu'à la fin, les points intermittents ne devraient pas apparaître. Les extraits suivants montrent comment j'ai configuré les transitions :

Je définis quelques fonctions qui créent mes "graphiques", puis je les appelle.

var makeCircle0 = function(){

  g.append("circle")
    .attr("cx", 50)
    .attr("cy", 100)
    .attr("r", 20)
    .attr("fill", "red")
    .attr("class", "redcircle")

  g.selectAll(".redcircle")
    .attr("opacity", 0)
}

makeCircle0();

// Faire la même chose pour makeCircle1, 2 et 3, également. 

Ensuite, je crée des fonctions pour gérer les transitions. Celle-ci dit de faire apparaître le cercle rouge et de mettre les autres cercles à une opacité de 0. Je fais ça pour tous les cercles/étapes.

var showCircle0 = function(){

  g.selectAll(".redcircle")
  .transition()
  .duration(1000)
  .attr("opacity", 1)

  g.selectAll(".yellowcircle").attr("opacity", 0)
  g.selectAll(".greencircle").attr("opacity", 0)
  g.selectAll(".bluecircle").attr("opacity", 0)

}

Cette section crée un tableau de mes fonctions de transition afin que je puisse les appeler à des étapes spécifiques de la page lorsque vous faites défiler. C'est similaire à la façon dont Jim Vallandingham a géré son défilement.

var activateFunctions = [];
activateFunctions[0] = showCircle0;
activateFunctions[1] = showCircle1;
activateFunctions[2] = showCircle2;
activateFunctions[3] = showCircle3;

Enfin, cela appelle la fonction désirée à la bonne étape de la page. Ce qui se produit... mais sans arrêter les autres transitions déclenchées à une étape précédente, ce qui entraîne l'apparition de plusieurs points à divers stades.

function handleStepEnter(response) {
  step.classed('is-active', function (d, i) {
    return i === response.index;
  })

  figure.call(activateFunctions[response.index])
}

Comment puis-je éviter cela ?

5voto

Andrew Reid Points 16844

Si vous avez besoin d'interrompre une transition, d3-transition possède une méthode pour cela:

selection.interrupt();

Cela annulera une transition sur une sélection. Si vous utilisez des transitions nommées, vous pouvez spécifier un nom en fournissant un argument à interrupt indiquant le nom de la transition à annuler.


S'il s'agit d'une version générique de votre fonction pour afficher un élément:

function show() {
  selectionToHide.attr("opacity",0);

  selectionToShow.transition()
     .attr("opacity",1);
}

Sans utiliser selection.interrupt, vous définissez l'opacité à zéro, et ensuite le prochain tick de toute transition en cours continue de mettre à jour l'opacité et termine d'exécuter la transition. En ajoutant interrupt nous évitons cela. Voici un exemple mis à jour.

Cependant, il existe une autre solution - nous pouvons appliquer une autre transition sur les éléments que nous ne voulons pas afficher. Pour cela, il suffit de remplacer la transition par une nouvelle:

function show() {
  selectionToHide.transition()
     .attr("opacity",0);

  selectionToShow.transition()
     .attr("opacity",1);
}

Cela remplacera les transitions sans nom existantes (comme les vôtres ne sont pas nommées) et fera disparaître progressivement les éléments, au lieu de les cacher tous en même temps. Voici un exemple de cela. Bien sûr, si vous avez de nombreux éléments, cela peut être affiné pour n'appliquer une transition qu'aux éléments en cours de transition (pas à ceux qui sont déjà cachés) afin de réduire le nombre de transitions actives.

Je n'ai pas touché au défilement, le cercle qui est affiché devrait avoir un index correspondant au nombre affiché, mais il semble que le nombre ne corresponde pas toujours à la position du défilement, mais c'est un problème distinct

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X