web-dev-qa-db-fra.com

Animation CSS: effet d'incrémentation numérique

Je veux obtenir cet effet d'animation lorsque les nombres changent rapidement, par exemple: http://jsbin.com/kevalutupe/1/

Je veux faire ce CSS seul (je sais comment le coder en JS), je ne veux pas utiliser JS car je pense que marteler le DOM n'est pas la meilleure solution. Est-ce possible avec CSS?

Je ne m'inquiète pas des chiffres qui augmentent correctement, je suis juste après l'effet.

13
ditto

L'effet de rotation de nombre est très certainement possible en utilisant des animations CSS3 et ce qui est mieux, vous pouvez également définir le point final en utilisant un petit peu de JS et obtenir réellement toutes les fonctionnalités.

Explication de la méthode:

  1. Un div est créé de telle sorte qu'il n'affichera toujours qu'un seul nombre en définissant sa hauteur et sa largeur sur 1em. Le débordement de div est réglé sur caché pour ne rendre visible qu'une seule ligne.
  2. Dans ce div un span contenant tous les nombres de 1 à 0 est créé et est positionné par rapport au parent.
  3. La position initiale du span est à 0px ou 0em mais pendant le animation la position supérieure est modifiée de sorte que le span donne l'impression d'être déplacé vers le haut. Étant donné que div ne peut afficher qu'un seul nombre à la fois, il donne l'effet de rotation (ou l'effet des autres nombres disparaissant).
  4. La position finale est obtenue en définissant une position supérieure fixe pour chacun des éléments span. 0em signifie que la 1ère ligne est visible (numéro 1), -2em signifie que la troisième ligne devient visible (numéro 3) et ainsi de suite.
  5. L'augmentation ou la diminution de la durée de l'animation rendra l'effet de rotation rapide ou lent. Le nombre d'itérations d'animation est défini sur 5 pour produire l'illusion que le spinner tourne plusieurs fois.

Remarque: En utilisant cette méthode, le spin ressemblera à parcourir le cercle entier à chaque fois et non pas à l'exemple JSBin en question où un 3 à 4 pour le premier chiffre ne serait qu'une étape et non un cercle complet.

div {
  width: 1em;
  height: 1em;
  overflow: hidden;
  line-height: 1em;
  display: inline-block;
}
span {
  position: relative;
}
.animate {
  -webkit-animation: spinit 0.2s 5;
  -moz-animation: spinit 0.2s 5;
  animation: spinit 0.2s 5;
}
@-webkit-keyframes spinit {
  0% {
    top: 0em;
  }
  50% {
    top: -5em;
  }
  100% {
    top: -9em;
  }
}
@-moz-keyframes spinit {
  0% {
    top: 0em;
  }
  50% {
    top: -5em;
  }
  100% {
    top: -9em;
  }
}
@keyframes spinit {
  0% {
    top: 0em;
  }
  50% {
    top: -5em;
  }
  100% {
    top: -9em;
  }
}

/* Setting the required value to top will make the spinner end at that number */

#digit1 {
  top: -4em;
  /* -4em means 5 will be the number */
}
#digit2 {
  top: -2em;
}
#digit3 {
  top: 0em;
}
<div>
  <span class="animate" id='digit1'>1 2 3 4 5 6 7 8 9 0</span>
</div>
<div>
  <span class="animate" id='digit2'>1 2 3 4 5 6 7 8 9 0</span>
</div>
<div>
  <span class="animate" id='digit3'>1 2 3 4 5 6 7 8 9 0</span>
</div>

Ce qui suit est un exemple avec JavaScript où l'effet d'animation est obtenu via CSS mais le déclenchement de l'animation et le paramétrage du point de terminaison est réalisé en utilisant JavaScript.

Le code JS est assez explicite. Tout ce que nous faisons est le suivant:

  1. Créez un écouteur pour l'événement click du bouton et à l'intérieur, nous ajoutons la classe animate à tous les éléments span qui font partie de cet effet d'animation. C'est parce que nous voulons que l'animation se produise uniquement lorsque le bouton est cliqué.
  2. Lorsque l'animation se termine (ou que la rotation est terminée), nous définissons la propriété top de chaque span sur un nombre aléatoire. Cela signifie que chaque plage aura un numéro différent affiché.
  3. À la fin de l'animation, nous appelons également une autre fonction pour supprimer la classe animate afin que lorsque nous cliquons à nouveau sur le bouton, l'animation puisse recommencer.
window.onload = function() {
  var spinner = document.getElementById('spinner');
  spinner.onclick = spinit;

  var el = document.querySelectorAll("span[id*=digit]");
  for (i = 0; i < el.length; i++) {
    el[i].addEventListener("animationend", randomize, false);
    el[i].addEventListener("webkitAnimationEnd", randomize, false);
    el[i].addEventListener("oanimationend", randomize, false);
    el[i].addEventListener("MSAnimationEnd", randomize, false);
  }
}

function randomize() {
  var Rand = Math.floor(Math.random() * 9);
  this.style.top = -1 * Rand + "em";
  this.classList.toggle('animate');
}

function spinit() {
  var el = document.querySelectorAll("span[id*=digit]");
  for (i = 0; i < el.length; i++) {
    el[i].classList.toggle('animate');
  }
}
div {
  width: 1em;
  height: 1em;
  overflow: hidden;
  line-height: 1em;
  display: inline-block;
}
span {
  position: relative;
}
.animate {
  -webkit-animation: spinit 0.2s 5;
  -moz-animation: spinit 0.2s 5;
  animation: spinit 0.2s 5;
}
@-webkit-keyframes spinit {
  0% {
    top: 0em;
  }
  50% {
    top: -5em;
  }
  100% {
    top: -9em;
  }
}
@-moz-keyframes spinit {
  0% {
    top: 0em;
  }
  50% {
    top: -5em;
  }
  100% {
    top: -9em;
  }
}
@keyframes spinit {
  0% {
    top: 0em;
  }
  50% {
    top: -5em;
  }
  100% {
    top: -9em;
  }
}

/* Set the value according to the on-load position of the spinner */

#digit1 {
  top: -4em;
  /* -4em means 5 will be the number */
}
#digit2 {
  top: -2em;
}
#digit3 {
  top: 0em;
}
<div>
  <span id='digit1'>1 2 3 4 5 6 7 8 9 0</span>
</div>

<div>
  <span id='digit2'>1 2 3 4 5 6 7 8 9 0</span>
</div>

<div>
  <span id='digit3'>1 2 3 4 5 6 7 8 9 0</span>
</div>

<button id='spinner'>Spin It</button>

Version 2: (avec seulement un effet d'incrémentation numérique au lieu d'un effet de rotation)

Ceci est créé en utilisant en grande partie le même code que le précédent mais contrairement au précédent où le animation rend le mouvement d'un nombre à l'autre graduel (et produisant ainsi un effet de rotation), ici l'animation fait le le mouvement ressemble plus à un saut soudain d'un nombre à un autre et produit ainsi juste un effet d'incrémentation.

Le saut est obtenu en maintenant la position top la même jusqu'à ce qu'il soit presque temps de passer à la suivante (c'est-à-dire que top est réglé sur 0em jusqu'à 9,9% de l'animation, mais à 10%, elle passe soudainement à -1em).

window.onload = function() {
  var spinner = document.getElementById('spinner');
  spinner.onclick = spinit;

  var el = document.querySelectorAll("span[id*=digit]");
  for (i = 0; i < el.length; i++) {
    el[i].addEventListener("animationend", randomize, false);
    el[i].addEventListener("webkitAnimationEnd", randomize, false);
    el[i].addEventListener("oanimationend", randomize, false);
    el[i].addEventListener("MSAnimationEnd", randomize, false);
  }
}

function randomize() {
  var Rand = Math.floor(Math.random() * 9);
  this.style.top = -1 * Rand + "em";
  this.classList.toggle('animate');
}

function spinit() {
  var el = document.querySelectorAll("span[id*=digit]");
  for (i = 0; i < el.length; i++) {
    el[i].classList.toggle('animate');
  }
}
div {
  width: 1em;
  height: 1em;
  overflow: hidden;
  line-height: 1em;
  display: inline-block;
}
span {
  position: relative;
}
.animate {
  -webkit-animation: spinit 0.2s 5;
  -moz-animation: spinit 0.2s 5;
  animation: spinit 0.2s 5;
}
@-webkit-keyframes spinit {
  0% { top: 0em; }
  9.9% { top: 0em; }
  10%{ top: -1em; }
  19.9%{ top: -1em; }
  20%{ top: -2em; }
  29.9%{ top: -2em; }
  30%{ top: -3em; }
  39.9%{ top: -3em; }
  40%{ top: -4em; }
  49.9%{ top: -4em; }
  50% { top: -5em; }
  59.9%{ top: -5em; }
  60%{ top: -6em; }
  69.9%{ top: -6em; }
  70%{ top: -7em; }
  79.9%{ top: -7em; }
  80%{ top: -8em; }
  89.9%{ top: -8em; }
  90%{ top: -9em; }
  99.9%{ top: -9em; }
  100% { top: -9em; }
}
@-moz-keyframes spinit {
  0% { top: 0em; }
  9.9% { top: 0em; }
  10%{ top: -1em; }
  19.9%{ top: -1em; }
  20%{ top: -2em; }
  29.9%{ top: -2em; }
  30%{ top: -3em; }
  39.9%{ top: -3em; }
  40%{ top: -4em; }
  49.9%{ top: -4em; }
  50% { top: -5em; }
  59.9%{ top: -5em; }
  60%{ top: -6em; }
  69.9%{ top: -6em; }
  70%{ top: -7em; }
  79.9%{ top: -7em; }
  80%{ top: -8em; }
  89.9%{ top: -8em; }
  90%{ top: -9em; }
  99.9%{ top: -9em; }
  100% { top: -9em; }
}
@keyframes spinit {
  0% { top: 0em; }
  9.9% { top: 0em; }
  10%{ top: -1em; }
  19.9%{ top: -1em; }
  20%{ top: -2em; }
  29.9%{ top: -2em; }
  30%{ top: -3em; }
  39.9%{ top: -3em; }
  40%{ top: -4em; }
  49.9%{ top: -4em; }
  50% { top: -5em; }
  59.9%{ top: -5em; }
  60%{ top: -6em; }
  69.9%{ top: -6em; }
  70%{ top: -7em; }
  79.9%{ top: -7em; }
  80%{ top: -8em; }
  89.9%{ top: -8em; }
  90%{ top: -9em; }
  99.9%{ top: -9em; }
  100% { top: -9em; }
}

/* Set the value according to the on-load position of the spinner */

#digit1 {
  top: -4em;
  /* -4em means 5 will be the number */
}
#digit2 {
  top: -2em;
}
#digit3 {
  top: 0em;
}
<div>
  <span id='digit1'>1 2 3 4 5 6 7 8 9 0</span>
</div>

<div>
  <span id='digit2'>1 2 3 4 5 6 7 8 9 0</span>
</div>

<div>
  <span id='digit3'>1 2 3 4 5 6 7 8 9 0</span>
</div>

<button id='spinner'>Spin It</button>
28
Harry