在使用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
});
});
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/