CSS-Animation neu starten

Avatar of Chris Coyier
Chris Coyier am

DigitalOcean bietet Cloud-Produkte für jede Phase Ihrer Reise. Starten Sie mit 200 $ kostenlosem Guthaben!

Mit CSS-Animationen (ala @keyframes) ist es nicht so einfach, wie man vielleicht denkt, sie "neu zu starten".

Nehmen wir an, Sie legen fest, dass sie einmal ausgeführt werden soll

.run-animation {
  animation: my-fancy-animation 5s 1; 
}

Sie lassen das zum Beispiel auf Ihrem Logo laufen

<h1 id="logo" class="run-animation">
  Fancy Logo
</h1>

Dann möchten Sie aus irgendeinem Grund, dass diese Animation erneut ausgeführt wird, vielleicht bei einem Klick. Sie denken vielleicht, dass CSS eine Möglichkeit bietet, sie erneut auszulösen, aber soweit ich weiß, tut es das nicht. Sie könnten sogar versuchen, den Klassennamen über JavaScript (jQuery) zu entfernen und wieder hinzuzufügen.

$("#logo").click(function() {
  // not gonna work
  $(this).removeClass("run-animation").addClass("run-animation");
});

Wenn Sie eine winzige Verzögerung zwischen dem Entfernen und erneuten Hinzufügen der Klasse einfügen (z. B. setTimeout()), funktioniert es, aber ich denke, es versteht sich von selbst, dass das nicht ideal ist. Was Sie wirklich tun müssen, ist, das Element vollständig von der Seite zu entfernen und es neu einzufügen. Als schnelle Demo mit jQuery klonen wir es, fügen es direkt daneben ein und entfernen dann das Original.

$("#logo").click(function() {	
	      	      
 var el     = $(this),  
     newone = el.clone(true);
           
 el.before(newone);
        
 $("." + el.attr("class") + ":last").remove();

});

oder die Grundlagen mit reinem JavaScript

const el = this;
var newone = elm.cloneNode(true);
elm.parentNode.replaceChild(newone, elm);

Demo ansehen

Dieses Problem besteht bei jeder Art von Ereignis. Sagen wir, Sie haben eine Animation, die sofort ausgeführt werden soll, und dann erneut bei :hover. Gleiches Problem, sie wird nicht erneut ausgeführt. Oli Studholme hat einige interessante Forschungsergebnisse dazu. Eine Möglichkeit, dies zu umgehen, besteht darin, zwei Animationen zu haben, die sich bis auf ihren Namen exakt gleichen, dann können Sie umschalten, welche Sie für das :hover-Ereignis (oder was auch immer) verwenden, und es wird funktionieren.

img        {animation: spin-cat-1 2s;}
img:active {animation: spin-cat-2 2s;}
@keyframes spin-cat-1 {50%{transform:rotateY(180deg);}}
@keyframes spin-cat-2 {50%{transform:rotateY(180deg);}}

Demo ansehen

Ein CSS-Präprozessor könnte helfen, dies einfacher zu verwalten, indem er einen Codeblock importiert, sodass Sie ihn nur an einer Stelle pflegen müssen, aber letztendlich ist das aufgebläht. Leider können Sie auch nicht mehrere Keyframe-Animationsnamen in einer Deklaration definieren, was ebenfalls nützlich wäre (und nicht nur dafür, denken Sie an komplexere Animationen, bei denen Sie nur bestimmte Keyframes über eine Basis-Keyframe-Animation neu schreiben könnten).

Oli hat auch mit einer Vielzahl anderer Techniken experimentiert, um es zum Laufen zu bringen, wie z. B. das Ändern von Dauer, Verzögerungen und Iterationen anstelle des Änderns des Namens, aber meiner Meinung nach sind all diese noch schlimmer als das Ändern des Namens.

Update: Eine weitere JavaScript-Methode zum Neustart einer CSS-Animation

Lösen Sie einen Reflow zwischen dem Entfernen und Hinzufügen des Klassennamens aus. Zum Beispiel

// retrieve the element
element = document.getElementById("logo");

// reset the transition by...
element.addEventListener("click", function(e) {
  e.preventDefault;
  
  // -> removing the class
  element.classList.remove("run-animation");
  
  // -> triggering reflow /* The actual magic */
  // without this it wouldn't work. Try uncommenting the line and the transition won't be retriggered.
  // Oops! This won't work in strict mode. Thanks Felis Phasma!
  // element.offsetWidth = element.offsetWidth;
  // Do this instead:
  void element.offsetWidth;
  
  // -> and re-adding the class
  element.classList.add("run-animation");
}, false);

Anderes JavaScript

Nur zur Vollständigkeit halber: Sie können den Wiedergabezustand einer CSS-Animation auch über JavaScript beeinflussen, z. B. pausieren und neu starten.

element.style.animationPlayState="paused";
element.style.animationPlayState="running";

// Vendor prefixed in old browsers
// element.style.webkitAnimationPlayState="paused";
// element.style.webkitAnimationPlayState="running";

Interessanterweise setzt das natürliche Ende einer CSS-Animation den Wiedergabezustand nicht auf "paused". Das müssten Sie selbst tun. Sagen wir, Sie möchten eine Animation bei jedem Hover neu starten und wären damit einverstanden, jQuery dafür zu verwenden...

$("#thing").hover(function() {
      
  this.style.animationPlayState = "running";

  $(this).on('animationEnd', function() {
    this.style.animationPlayState = "paused";
  });
        
});

Beachten Sie, wie Sie auf das Ereignis AnimationEnd warten müssen, damit es ausgelöst wird, um es wieder auf "paused" zu setzen, sonst wird es nicht richtig neu gestartet.