web-dev-qa-db-fra.com

Animation CSS retarder la répétition

J'ai récemment découvert comment utiliser "correctement" les animations CSS (auparavant, je les rejetais, car je ne pouvais pas créer de séquences complexes comme vous le pouvez en JavaScript). Alors maintenant, j'apprends à leur sujet.

Pour cet effet, j'essaie d'avoir un dégradé "éclairé" sur un élément en forme de barre de progression. Semblable à l’effet sur les barres de progression natives de Windows Vista/7.

@keyframes barshine {
  from {background-image:linear-gradient(120deg,rgba(255,255,255,0) -10%,rgba(255,255,255,0.25) -5%,rgba(255,255,255,0) 0%);}
  to {background-image:linear-gradient(120deg,rgba(255,255,255,0) 100%,rgba(255,255,255,0.25) 105%,rgba(255,255,255,0) 110%);}
}
.progbar {
  animation: barshine 1s 4s linear infinite;
}

Comme vous pouvez le constater, j'essaie d'avoir un délai de 4 secondes, suivi d'un balayage brillant en 1 seconde, répété.

Cependant, il semble que le animation-delay s’applique uniquement à la première itération, après quoi la brillance continue de balayer à plusieurs reprises.

J'ai "résolu" ce problème comme suit:

@keyframes expbarshine {
  from {background-image:linear-gradient(120deg,rgba(255,255,255,0) -10%,rgba(255,255,255,0.25) -5%,rgba(255,255,255,0) 0%);}
  80% {background-image:linear-gradient(120deg,rgba(255,255,255,0) -10%,rgba(255,255,255,0.25) -5%,rgba(255,255,255,0) 0%);}
  to {background-image:linear-gradient(120deg,rgba(255,255,255,0) 100%,rgba(255,255,255,0.25) 105%,rgba(255,255,255,0) 110%);}
}
.progbar {
  animation: barshine 5s linear infinite;
}

from et 80% sont exactement les mêmes, ce qui entraîne un "retard" de 80% de la longueur de l'animation.

Cela fonctionne, mais pour ma prochaine animation, le délai doit être variable (constant pour un élément particulier, mais variable pour les éléments qui utilisent l'animation), tandis que l'animation elle-même reste exactement de la même longueur.

Avec la "solution" ci-dessus, je me retrouverais avec une animation plus lente quand tout ce que je veux, c'est un délai plus long.

Est-il possible d'avoir le animation-delay s'applique-t-il à toutes les itérations, plutôt qu'à la première?

64
Niet the Dark Absol

J'ai eu un problème similaire et utilisé

@-webkit-keyframes pan {
   0%, 10%       { -webkit-transform: translate3d( 0%, 0px, 0px); }
   90%, 100%     { -webkit-transform: translate3d(-50%, 0px, 0px); }
}

Peu irritant que vous deviez simuler votre temps pour tenir compte des "retards" aux deux extrémités.

49
Sebastian Thomas

minitech a raison en ce que animation-delay spécifie le délai avant le début de l'animation et [~ # ~] et non [~ # ~] le délai entre les itérations. Le brouillon de la spécification par les éditeurs le décrit bien et il y a eu une discussion sur cette fonctionnalité que vous décrivez ici qui suggère cette fonctionnalité de délai d'itération.

Bien qu'il puisse y avoir une solution de contournement dans JS, vous pouvez simuler ce délai d'itération pour le flare de barre de progression en utilisant uniquement CSS.

En déclarant la fusée div position:absolute et le parent div overflow: hidden, en définissant l'état d'image clé à 100% supérieur à la largeur de la barre de progression, et en jouant avec la fonction de minutage cubique-bezier et les valeurs de décalage à gauche, vous pouvez émuler un ease-in-out ou linear chronométrage avec un "délai".

Il serait intéressant d’écrire un mixin less/scss pour calculer exactement le décalage gauche et la fonction de minutage afin d’obtenir cette précision, mais je n’ai pas le temps pour le jouer. J'aimerais voir quelque chose comme ça si!

Voici une démo que j'ai réunie pour montrer cela. (J'ai essayé d'imiter la barre de progression de Windows 7 et suis tombé un peu court, mais cela montre de quoi je parle)

Démo: http: //codepen.io/timothyasp/full/HlzGu

<!-- HTML -->
<div class="bar">
   <div class="progress">
      <div class="flare"></div>
   </div>
</div>


/* CSS */

@keyframes progress {
  from {
    width: 0px;
  }
  to {
    width: 600px;
  }
}

@keyframes barshine {
  0% {
    left: -100px;
  }

  100% {
    left: 1000px;
  }
}
.flare {
  animation-name: barshine;
  animation-duration: 3s;
  animation-direction: normal;
  animation-fill-mode: forwards;
  animation-timing-function: cubic-bezier(.14, .75, .2, 1.01);
  animation-iteration-count: infinite;
  left: 0;
  top: 0;
  height: 40px;
  width: 100px;
  position: absolute;
  background: -moz-radial-gradient(center, ellipse cover,  rgba(255,255,255,0.69) 0%, rgba(255,255,255,0) 87%); /* FF3.6+ */
  background: -webkit-gradient(radial, center center, 0px, center center, 100%, color-stop(0%,rgba(255,255,255,0.69)), color-stop(87%,rgba(255,255,255,0))); /* Chrome,Safari4+ */
  background: -webkit-radial-gradient(center, ellipse cover,  rgba(255,255,255,0.69) 0%,rgba(255,255,255,0) 87%); /* Chrome10+,Safari5.1+ */
  background: -o-radial-gradient(center, ellipse cover,  rgba(255,255,255,0.69) 0%,rgba(255,255,255,0) 87%); /* Opera 12+ */
  background: -ms-radial-gradient(center, ellipse cover,  rgba(255,255,255,0.69) 0%,rgba(255,255,255,0) 87%); /* IE10+ */
  background: radial-gradient(ellipse at center,  rgba(255,255,255,0.69) 0%,rgba(255,255,255,0) 87%); /* W3C */
  filter: progid:DXImageTransform.Microsoft.gradient( startColorstr='#b0ffffff', endColorstr='#00ffffff',GradientType=1 ); /* IE6-9 fallback on horizontal gradient */
  z-index: 10;
}
.progress {
  animation-name: progress;
  animation-duration: 10s;
  animation-delay: 1s;
  animation-timing-function: linear;
  animation-iteration-count: infinite;
  overflow: hidden;
  position:relative;
  z-index: 1;
  height: 100%;
  width: 100%;
  border-right: 1px solid #0f9116;
  background: #caf7ce; /* Old browsers */
  background: -moz-linear-gradient(top, #caf7ce 0%, #caf7ce 18%, #3fe81e 45%, #2ab22a 96%); /* FF3.6+ */
  background: -webkit-gradient(linear, left top, left bottom, color-stop(0%,#caf7ce), color-stop(18%,#caf7ce), color-stop(45%,#3fe81e), color-stop(96%,#2ab22a)); /* Chrome,Safari4+ */
  background: -webkit-linear-gradient(top, #caf7ce 0%,#caf7ce 18%,#3fe81e 45%,#2ab22a 96%); /* Chrome10+,Safari5.1+ */
  background: -o-linear-gradient(top, #caf7ce 0%,#caf7ce 18%,#3fe81e 45%,#2ab22a 96%); /* Opera 11.10+ */
  background: -ms-linear-gradient(top, #caf7ce 0%,#caf7ce 18%,#3fe81e 45%,#2ab22a 96%); /* IE10+ */
  background: linear-gradient(to bottom, #caf7ce 0%,#caf7ce 18%,#3fe81e 45%,#2ab22a 96%); /* W3C */
filter: progid:DXImageTransform.Microsoft.gradient( startColorstr='#caf7ce', endColorstr='#2ab22a',GradientType=0 ); /* IE6-9 */
}

.progress:after {
  content: "";
  width: 100%;
  height: 29px;
  right: 0;
  bottom: 0;
  position: absolute;
  z-index: 3;
  background: -moz-linear-gradient(left, rgba(202,247,206,0) 0%, rgba(42,178,42,1) 100%); /* FF3.6+ */
  background: -webkit-gradient(linear, left top, right top, color-stop(0%,rgba(202,247,206,0)), color-stop(100%,rgba(42,178,42,1))); /* Chrome,Safari4+ */
  background: -webkit-linear-gradient(left, rgba(202,247,206,0) 0%,rgba(42,178,42,1) 100%); /* Chrome10+,Safari5.1+ */
  background: -o-linear-gradient(left, rgba(202,247,206,0) 0%,rgba(42,178,42,1) 100%); /* Opera 11.10+ */
  background: -ms-linear-gradient(left, rgba(202,247,206,0) 0%,rgba(42,178,42,1) 100%); /* IE10+ */
  background: linear-gradient(to right, rgba(202,247,206,0) 0%,rgba(42,178,42,1) 100%); /* W3C */
  filter: progid:DXImageTransform.Microsoft.gradient( startColorstr='#00caf7ce', endColorstr='#2ab22a',GradientType=1 ); /* IE6-9 */
}

.bar {
  margin-top: 30px;
  height: 40px;
  width: 600px;
  position: relative;
  border: 1px solid #777;
  border-radius: 3px;
}
17
tim

C'est ce que tu devrais faire. Cela devrait fonctionner car vous avez une animation d'une seconde, puis un délai de 4 secondes entre les itérations:

@keyframes barshine {
  0% {
  background-image:linear-gradient(120deg,rgba(255,255,255,0) 0%,rgba(255,255,255,0.25) -5%,rgba(255,255,255,0) 0%);
  }
  20% {
    background-image:linear-gradient(120deg,rgba(255,255,255,0) 10%,rgba(255,255,255,0.25) 105%,rgba(255,255,255,0) 110%);
  }
}
.progbar {
  animation: barshine 5s 0s linear infinite;
}

Donc, je me suis beaucoup amusé avec ça et tu peux le faire sans être très méchant. C’est le moyen le plus simple d’établir un délai entre les itérations d’animation de 1. SUPER EASY et 2. prend juste un peu de logique. Découvrez cette animation de danse que j'ai faite:

.dance{
  animation-name: dance;
  -webkit-animation-name: dance;

  animation-iteration-count: infinite;
  -webkit-animation-iteration-count: infinite;
  animation-duration: 2.5s;
  -webkit-animation-duration: 2.5s;

  -webkit-animation-delay: 2.5s;
  animation-delay: 2.5s;
  animation-timing-function: ease-in;
  -webkit-animation-timing-function: ease-in;

}
@keyframes dance {
  0% {
    -webkit-transform: rotate(0deg);
    -moz-transform: rotate(0deg);
    -o-transform: rotate(0deg);
    -ms-transform: rotate(0deg);
    transform: rotate(0deg);
  }
  25% {
    -webkit-transform: rotate(-120deg);
    -moz-transform: rotate(-120deg);
    -o-transform: rotate(-120deg);
    -ms-transform: rotate(-120deg);
    transform: rotate(-120deg);
  }
  50% {
    -webkit-transform: rotate(20deg);
    -moz-transform: rotate(20deg);
    -o-transform: rotate(20deg);
    -ms-transform: rotate(20deg);
    transform: rotate(20deg);
  }
  100% {
    -webkit-transform: rotate(0deg);
    -moz-transform: rotate(0deg);
    -o-transform: rotate(0deg);
    -ms-transform: rotate(0deg);
    transform: rotate(0deg);
  }
}

@-webkit-keyframes dance {
  0% {
    -webkit-transform: rotate(0deg);
    -moz-transform: rotate(0deg);
    -o-transform: rotate(0deg);
    -ms-transform: rotate(0deg);
    transform: rotate(0deg);
  }
  20% {
    -webkit-transform: rotate(20deg);
    -moz-transform: rotate(20deg);
    -o-transform: rotate(20deg);
    -ms-transform: rotate(20deg);
    transform: rotate(20deg);
  }
  40% {
    -webkit-transform: rotate(-120deg);
    -moz-transform: rotate(-120deg);
    -o-transform: rotate(-120deg);
    -ms-transform: rotate(-120deg);
    transform: rotate(-120deg);
  }
  60% {
    -webkit-transform: rotate(0deg);
    -moz-transform: rotate(0deg);
    -o-transform: rotate(0deg);
    -ms-transform: rotate(0deg);
    transform: rotate(0deg);
  }
  80% {
    -webkit-transform: rotate(-120deg);
    -moz-transform: rotate(-120deg);
    -o-transform: rotate(-120deg);
    -ms-transform: rotate(-120deg);
    transform: rotate(-120deg);
  }
  95% {
    -webkit-transform: rotate(20deg);
    -moz-transform: rotate(20deg);
    -o-transform: rotate(20deg);
    -ms-transform: rotate(20deg);
    transform: rotate(20deg);
  }
}

En fait, je suis venu ici pour essayer de trouver un moyen de retarder l'animation, quand je me suis rendu compte qu'il suffisait 1. d'allonger la durée de l'animation et de définir la proportion de temps pour chaque animation. Beore, je les ai eu chacun pendant 0,5 seconde pour une durée totale de 2,5 secondes. Maintenant, disons que je voulais ajouter un délai égal à la durée totale, donc un délai de 2,5 secondes.

Le temps d'animation est de 2,5 secondes et le délai est de 2,5 secondes. Vous modifiez donc la durée à 5 secondes. Cependant, comme vous avez doublé la durée totale, vous souhaiterez réduire de moitié la proportion d'animations. Vérifiez la finale ci-dessous. Cela a parfaitement fonctionné pour moi.

@-webkit-keyframes dance {
  0% {
    -webkit-transform: rotate(0deg);
    -moz-transform: rotate(0deg);
    -o-transform: rotate(0deg);
    -ms-transform: rotate(0deg);
    transform: rotate(0deg);
  }
  10% {
    -webkit-transform: rotate(20deg);
    -moz-transform: rotate(20deg);
    -o-transform: rotate(20deg);
    -ms-transform: rotate(20deg);
    transform: rotate(20deg);
  }
  20% {
    -webkit-transform: rotate(-120deg);
    -moz-transform: rotate(-120deg);
    -o-transform: rotate(-120deg);
    -ms-transform: rotate(-120deg);
    transform: rotate(-120deg);
  }
  30% {
    -webkit-transform: rotate(0deg);
    -moz-transform: rotate(0deg);
    -o-transform: rotate(0deg);
    -ms-transform: rotate(0deg);
    transform: rotate(0deg);
  }
  40% {
    -webkit-transform: rotate(-120deg);
    -moz-transform: rotate(-120deg);
    -o-transform: rotate(-120deg);
    -ms-transform: rotate(-120deg);
    transform: rotate(-120deg);
  }
  50% {
    -webkit-transform: rotate(0deg);
    -moz-transform: rotate(0deg);
    -o-transform: rotate(0deg);
    -ms-transform: rotate(0deg);
    transform: rotate(0deg);
  }
}

En somme:

Ce sont les calculs que vous utiliseriez probablement pour déterminer comment modifier la durée de votre animation et le% de chaque partie.

durée souhaitée = x

durée_animée = animation_part_duration1 + animation_part_duration2 + ... (et ainsi de suite)

désirée = y

durée totale = x + y

animation_part_duration1_actual = animation_part_duration1 * durée souhaitée/durée totale

8
TalkativeTree

Je préférerais écrire un peu de JavaScript que de rendre le CSS moins facile à gérer.

Tout d'abord, appliquez uniquement l'animation CSS sur un changement d'attribut de données:

.progbar[data-animation="barshine"] {
    animation: barshine 1s linear;
}

Ajoutez ensuite du javascript pour basculer l'animation à la moitié du délai.

var progbar = document.querySelector('.progbar');
var on = false;

setInterval(function () {
    progbar.setAttribute('data-animation', (on) ? 'barshine' : '');
    on = !on;
}, 3000);

Ou si vous ne souhaitez pas que l'animation s'exécute lorsque l'onglet est masqué:

var progbar = document.querySelector('.progbar');
var on = false;

var update = function () {
    progbar.setAttribute('data-animation', (on) ? 'barshine' : '');
    on = !on;
    setTimer();
};

var setTimer = function () {
    setTimeout(function () {
        requestAnimationFrame(update);
    }, 3000);
};

setTimer();
5
cuth

Voici un petit extrait qui montre la même chose pendant 75% du temps, puis il glisse. Ce schéma de répétition émule bien le délai:

@-webkit-keyframes slide    {
0%   {background-position: 0 0;}
25%  {background-position: 0 0;}
50%  {background-position: 0 0;}
75%  {background-position: 0 0;}
100% {background-position: 13em 0;}
}

@-moz-keyframes slide       {
0%   {background-position: 0 0;}
25%  {background-position: 0 0;}
50%  {background-position: 0 0;}
75%  {background-position: 0 0;}
100% {background-position: 13em 0;}
}

@keyframes slide            {
0%   {background-position: 0 0;}
25%  {background-position: 0 0;}
50%  {background-position: 0 0;}
75%  {background-position: 0 0;}
100% {background-position: 13em 0;}
}
2
nolook

J'ai fait une affiche sur le mur qui avance à gauche et à droite. Pour moi ça marche:

.div-animation {
   -webkit-animation: bounce 2000ms ease-out;
    -moz-animation: bounce 2000ms ease-out;
    -o-animation: bounce 2000ms ease-out;
    animation: bounce 2000ms ease-out infinite;
    -webkit-animation-delay: 2s; /* Chrome, Safari, Opera */
    animation-delay: 2s;
    transform-Origin: 55% 10%;    
}

@-webkit-keyframes bounce {
    0% {
        transform: rotate(0deg);
    }
    3% {
        transform: rotate(1deg);
    }
    6% {
        transform: rotate(2deg);
    }
    9% {
        transform: rotate(3deg);
    }
    12% {
        transform: rotate(2deg);
    }
    15% {
        transform: rotate(1deg);
    }
    18% {
        transform: rotate(0deg);
    }
    21% {
        transform: rotate(-1deg);
    }
    24% {
        transform: rotate(-2deg);
    }
    27% {
        transform: rotate(-3deg);
    }
    30% {
        transform: rotate(-2deg);
    }
    33% {
        transform: rotate(-1deg);
    }
    36% {
        transform: rotate(0deg);
    }
    100% {
        transform: rotate(0deg);
    }
}
2
Bubas

Le retard n’est possible qu’une fois au début avec une infinité. Le délai de tri ne fonctionne pas avec une boucle infinie. pour cela, vous devez conserver des exemples d’animations d’animations d’images clés:

@-webkit-keyframes barshine {
  10% {background: -webkit-gradient(linear, left top, left bottom, color-stop(0%,#1e5799), color-stop(100%,#7db9e8));
    }
  60% {background: -webkit-linear-gradient(top, #7db9e8 0%,#d32a2d 100%);}
}

il animera 10% à 60% et attendra pour compléter 40% de plus. Donc 40% arrivent en retard.

trouver un exemple de violon

0
Ganesh Yadav