animationend事件监听CSS动画结束及兼容代码

在使用CSS3动画中,会有需要监听动画是否已经结束并对事件进行处理,最好的方法就是使用animationend。我们通过JavaScript来监听动画的开始、进行和结束,这样子方便我们随时控制运动中的元素。

在用JS控制动画的时候,看着setTimeout总是不爽。并且存在以下问题:

1. 你需要在两个地方规定动画时间,css和js。

2.并不十分准确,回调可能会滞后。你只能希望你的CSS和JS以同样的速度执行,不过这当然只是理想的状态。

于是,更好的一种解决方案出现了——transitionend事件和animationend事件。

本文主要介绍animationend事件,关于transitionend事件请看前面的文章.

CSS 动画播放时,会发生以下三个事件:

  • animationstart -CSS 动画开始后触发
  • animationiteration – CSS 动画重复播放时触发
  • animationend – CSS 动画完成后触发

下面这个代码演示了 <div> 元素添加监听事件:

// set the var here
var monkey = document.querySelector("#monkey");

// listen for animation start
monkey.addEventListener("animationstart",function(e){
    console.log("log at beginning of monkey animation");
},false);

// listen for animation iteration
monkey.addEventListener("animationiteration",function(e){
    console.log("log at beginning of each subsequent iteration");
},false);

// listen for animation end
monkey.addEventListener("animationend",function(e){
    console.log("log at end of monkey animation");
},false);

浏览器支持

不同的浏览器要求使用不同的前缀,具体写法如下:

  • No prefix – animationstart, animationiteration, animationend
  • Webkit – webkitAnimationStart, webkitAnimationIteration, webkitAnimationEnd
  • Mozilla – mozAnimationStart, mozAnimationIteration, mozAnimationEnd
  • MS – MSAnimationStart, MSAnimationIteration, MSAnimationEnd
  • O – oAnimationStart, oAnimationIteration, oAnimationEnd

如果在写代码中,要求这5个都写上那会很麻烦,幸运的是我们可以通过一个函数来解决这个麻烦。

// prefixer helper function
var pfx = ["webkit", "moz", "MS", "o", ""];
function prefixedEventListener(element, type, callback) {
    for (var p = 0; p < pfx.length; p++) {
        if (!pfx[p]) type = type.toLowerCase();
        element.addEventListener(pfx[p]+type, callback, false);
    }
}

// new event listener function
var monkey = document.querySelector("#monkey");
prefixedEventListener(monkey,"AnimationStart",function(e){
    console.log("log at beginning of monkey animation");
});

附录网上的另外一种解决方法:

function whichAnimationEvent(){
  var t,
      el = document.createElement("fakeelement");

  var animations = {
    "animation"      : "animationend",
    "OAnimation"     : "oAnimationEnd",
    "MozAnimation"   : "animationend",
    "WebkitAnimation": "webkitAnimationEnd"
  }

  for (t in animations){
    if (el.style[t] !== undefined){
      return animations[t];
    }
  }
}

var animationEvent = whichAnimationEvent();

$(".button").click(function(){
  $(this).addClass("animate");
  $(this).one(animationEvent,
              function(event) {
    // Do something when the animation ends
  });
});

原生JavaScript

With Vanilla JavaScript, it’s slightly trickier. Using thewhichTransitionEvent function, bind transitionEvent withaddEventListener.

var button = document.querySelector(".button"),
    transitionEvent = whichTransitionEvent();

button.addEventListener("click", function() {
  if (button.classList) {
    button.classList.add("animate");
  } else {
    button.className += " " + "animate";
  }

  button.addEventListener(transitionEvent, customFunction);
});

function customFunction(event) {
  button.removeEventListener(transitionEvent, customFunction);

  // Do something when the transition ends
}

参考文章:

http://callmenick.com/post/listen-for-css-animation-events-with-javascript
https://jonsuh.com/blog/detect-the-end-of-css-animations-and-transitions-with-javascript/


关注我

我的微信公众号:前端开发博客,在后台回复以下关键字可以获取资源。

  • 回复「小抄」,领取Vue、JavaScript 和 WebComponent 小抄 PDF
  • 回复「Vue脑图」获取 Vue 相关脑图
  • 回复「思维图」获取 JavaScript 相关思维图
  • 回复「简历」获取简历制作建议
  • 回复「简历模板」获取精选的简历模板
  • 回复「加群」进入500人前端精英群
  • 回复「电子书」下载我整理的大量前端资源,含面试、Vue实战项目、CSS和JavaScript电子书等。
  • 回复「知识点」下载高清JavaScript知识点图谱

每日分享有用的前端开发知识,加我微信:caibaojian89 交流