重新启动 CSS 动画

Avatar of Chris Coyier
Chris Coyier

DigitalOcean 为您旅程的每个阶段提供云产品。立即开始使用 200 美元的免费积分!

使用 CSS 动画(例如 @keyframes),“重新启动”它并不像您想象的那么容易。

假设您将其设置为运行一次

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

您可以在您的徽标上运行它

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

然后出于某种原因,您希望该动画再次运行,也许是在点击时。您可能认为 CSS 提供了一种方法来再次启动它,但据我所知,它没有。您甚至可以尝试通过 JavaScript(jQuery)删除和重新添加该类名

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

如果您在删除和重新添加类之间设置一个很小的延迟(例如 setTimeout()),它将起作用,但我认为不必说这不是理想的。您真正需要做的是完全从页面中删除元素并重新插入它。作为使用 jQuery 的快速演示,我们将克隆它,将其插入其自身之后,然后删除原始元素。

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

});

或仅使用 JavaScript 的基础知识

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

查看演示

任何类型的事件都存在同样的问题。假设您有一个希望立即运行的动画,然后在 :hover 上再次运行。同样的问题,它不会再次运行。Oli Studholme 对此进行了一些有趣的研究。一种解决方法是使用两个动画,这两个动画完全相同,除了它们的名称,然后您可以切换在 :hover 事件(或任何事件)中使用哪个动画,它将起作用。

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);}}

查看演示

CSS 预处理器可以通过导入代码块来帮助简化维护,因此您只需在一个地方维护它,但这最终会造成膨胀。不幸的是,您也不能在一个声明中定义多个关键帧动画名称,这也很有用(不仅限于此,想想更复杂的动画,您可以在基本关键帧动画的基础上重写某些关键帧)。

Oli 还 尝试了各种其他技术 来使其工作,例如更改持续时间、延迟和迭代次数而不是更改名称,但在我看来,所有这些都比更改名称更糟糕。

更新:另一种重新启动 CSS 动画的 JavaScript 方法

在删除和添加类名之间触发回流。例如

// 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);

其他 JavaScript

仅供参考,您还可以通过 JavaScript 影响 CSS 动画的播放状态,例如暂停和重新启动它。

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

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

有趣的是,CSS 动画的自然结束不会将播放状态设置为“暂停”。您必须自己执行此操作。假设您希望在每次悬停时重新启动动画,并且您很乐意使用 jQuery 来执行此操作……

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

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

请注意,您必须监视 AnimationEnd 事件的触发以将其设置回“暂停”,否则它将无法正确重新启动。