css3动画事件transitionend和animationend详解

在做界面的时候通常会使用css3的transitionanimation属性来实现动画效果,假如有这样一种需求——在动画执行完成后需要执行自定义业务逻辑,如抽奖转盘、拆红包、小游戏等场景,这个时候需要怎么去实现呢?

方法一

使用定时器setTimeout,设定一个和动画时长一样的time,过time时间后去执行业务逻辑。

setTimeout(function () {}, time);

这种方式简单除暴,一定程度上能满足需求,但更好是方式是使用transitionendanimationend事件。

方法二

transitionendanimationend是JavaScript原生支持的事件,对应css3的transitionanimation属性。

transitionend

示例:

var transitionEle = document.querySelector("#transition_ele");  
transitionEle.addEventListener("transitionend", function () {}, false);

注意:

transitionend事件会在 css transition 结束后触发。 当transition完成前移除transition时,比如移除css的transition-property属性,事件将不会被触发,如在transition完成前设置 display 为”none”,事件同样不会被触发。

关于transitionend事件的多次执行。假如设置transitionProperty=“width,height,background-color,transform”,这里width、height、background-color、transform四个属性都被改变了,那么这个时候transitionend会执行4次,这是因为transitionend事件执行了几次是取决于transition-property的设置(如果某个属性没有改变值,那么是不会触发transitionend的事件)。而在实际的运用中,往往只需要所有的动画结束后执行一次transitionend的事件来达效果,这个时候就需要做一些处理,让transitionend事件在多个css属性改变的情况下执行一次,示例:

var transitionFlag = true;  
transitionEle.addEventListener("transitionend", function (e) {  
    // or e.target === this  
  if (e.target === e.currentTarget && transitionFlag) {  
        transitionFlag = false;  
  // do something  
  }  
}, false);

兼容:

由于各个浏览器有不同的前缀,所以使用JavaScript代码时还要检测支持哪种,示例:

/* From Modernizr */
function whichTransitionEvent() {
    var t;
    var el = document.createElement('fakeelement');
    var transitions = {
        'transition'		: 'transitionend',
        'OTransition'		: 'oTransitionEnd',
        'MozTransition'		: 'transitionend',
        'WebkitTransition'	: 'webkitTransitionEnd'
    }
    for(t in transitions){
        if( el.style[t] !== undefined ){
            return transitions[t];
        }
    }
}
/* Listen for a transition! */
var transitionEvent = whichTransitionEvent();
transitionEvent && transitionEle.addEventListener(transitionEvent, function () {
    console.log('Transition complete!  This is the callback, no library needed!');
});

animationend

事实上animation动画有三个事件:

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

示例:

var animationEle = document.querySelector("#animation_ele");  
// 动画开始时事件  
animationEle.addEventListener("animationstart", function () {}, false);  
// 动画重复运动时事件  
animationEle.addEventListener("animationiteration", function () {}, false);  
// 动画结束时事件  
animationEle.addEventListener("animationend", function () {}, false);

注意:

animationend事件会在一个 css动画完成时触发(不包括完成前就已终止的情况,例如元素变得不可见或者动画从元素中移除)。

关于animationend事件的多次执行。不同于transitionend事件,animationend只会在动画完成后执行一次,但是如果在外层添加这个监听事件,并且监听元素里面还有动画,则里面元素动画结束也会执行这个animationend事件,这个时候就需要做一些处理,示例:

var animationFlag = true;  
animationEle.addEventListener("animationend", function (e) {  
    // or e.target === this  
  if (e.target === e.currentTarget && animationFlag) {  
        animationFlag = false;  
  // do something  
  }  
}, false);

兼容:

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

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

兼容方法:

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();
animationEvent && animationEle.addEventListener(animationEvent, function () {
    console.log('Animation complete!  This is the callback, no library needed!');
});

发表评论

电子邮件地址不会被公开。 必填项已用*标注

此站点使用Akismet来减少垃圾评论。了解我们如何处理您的评论数据