transitionend animationend 事件兼容问题

来源:互联网 发布:罗宇回忆录 知乎 编辑:程序博客网 时间:2024/06/05 13:27

      平时在做动画的时候,如果涉及交互比较多一些的时候。比如像拆礼盒,摇筛子等基于微信的小游戏,transitionend和animationend这个两个事件都会用到,之前做微信的小游戏过程中,把两个事件在pc端和移动端的常用的浏览器给测试了一下并做了整理,虽然浏览器的支持结果大同小异,但是还是有一些细微的差别的,其中微信和qq浏览器(其实是同一个)对于两个事件都需要加前缀!

一、transitionend事件

       1.浏览器支持情况

01

      注:transitionend的事件只有三种形式,之所以不检测MozTransitionEndmsTransitionEnd 这两个的事件,因为火狐和IE都已经支持了transitionend,相反的对于加前缀反而不执行事件,oTransitionEnd  代表的是欧朋浏览器,transitionend 一定要小写 否则浏览器不识别,webkitTransitionEnd中T和E是一定要大写的,w大小写是无所谓的!

       2.transitionend有过渡效果的css属性

      为什么要知道有过渡css属性的呢?首先是,实例运用中,经常会发现,一个元素起始时的display:none,想通过transition来实现动画过渡效果,结果发现不行,因为display没有过渡效果! 其次,有过渡的css属性决定了transtionend的执行次数(下面会说),在transitionDuration的时间不为0的时候,有过渡效果的css属性,也就transition-property支持的css的属性有:

02

      3.transitionend事件的多次执行

     transitionend事件执行了几次是取决于transition-property的设置,假设我们设置transitionProperty="width,height,background-color,transform",那么这个时候你应该猜测得到transitionend执行了4次(如果某个属性没有改变值,那么是不会触发transitionend的事件),尝试运行下面的代码就知道:

<!DOCTYPE html><html lang="en"><head><meta charset="UTF-8"><meta name="viewport" content="width=device-width,minimum-scale=1.0,maximum-scale=1.0"/><title>transitionend - 蜗牛博客(wnworld.com)</title><link rel="stylesheet" type="text/css" href="http://wnworld.com/wp-content/themes/temp1/css/reset.css"></head><body><style type="text/css">.movebox{width:50px;height:50px;position: relative;background:#f60;-webkit-transition-duration: 1s;-o-transition-duration: 1s;transition-duration: 1s;-webkit-transition-timing-function: linear;-o-transition-timing-function: linear;transition-timing-function: linear;}</style><div class="movebox" id="J_movebox"></div><div class="handguide-btn fixed align-c "><a href="javascript:void(0)" class="wn-btn wn-btn-success" id="J_movingbtn">&nbsp;&nbsp;运动&nbsp;&nbsp; </a> <a href="javascript:void(0)" class="wn-btn wn-btn-success" id="J_returnbeginbtn">&nbsp;&nbsp;恢复&nbsp;&nbsp; </a> </div><script type="text/javascript">var movebox=document.getElementById("J_movebox"),btn=document.getElementById("J_movingbtn"),returnbeginbtn=document.getElementById("J_returnbeginbtn"),i=0,transition="transition",body=document.body || document.documentElement,style=body.style;vartransitionEnd=(function(){var transEndEventNames = {      WebkitTransition : 'webkitTransitionEnd',      MozTransition    : 'transitionend',      OTransition      : 'oTransitionEnd otransitionend',      transition       : 'transitionend'    }for(var name in transEndEventNames){if(typeof style[name] === "string"){return transEndEventNames[name]}}})();var vendorPrefix=(function(){var i=0, vendor=["Moz", "Webkit", "Khtml", "O", "ms"];transition=transition.charAt(0).toUpperCase() + transition.substr(1);   while (i < vendor.length) {if (typeof style[vendor[i] + transition] === "string") {  return vendor[i];}i++;}return false;})();movebox.addEventListener(transitionEnd,function(){i++;alert("第"+i+"次执行"+transitionEnd+"事件!")},false)btn.onclick=function(){                                i=0;movebox.style.width="150px";movebox.style.height="150px";movebox.style.backgroundColor="#000";movebox.style[vendorPrefix+"Transform"]="translate(100px,100px) rotate(45deg)";movebox.style[vendorPrefix+"TransitionProperty"]="width,height,background-color,transform";}returnbeginbtn.onclick=function(){i=0;movebox.style.width="50px";movebox.style.height="50px";movebox.style.backgroundColor="#f60";movebox.style[vendorPrefix+"Transform"]="translate(0px,0px) rotate(0deg)";movebox.style[vendorPrefix+"TransitionProperty"]="width,height,background-color,transform";}</script></body></html>
运行

      结果很明显:transitionend触发了四次,因为width,height,background-color,transform四个属性都被改变了!而在实际的运用中,我们往往只需要所有的动画结束后执行一次transitionend的事件来达做我们想要做的事情,这个时候就需要我们做一些处理,让transitionend事件在多个css属性改变的情况下执行一次,现在定义一个函数handleTransitionEndEvent来处理多次触发的问题:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
var handleTransitionEndEvent=function(elem,fn,duration){
    var called=false;
    //在每次transitionEnd的事件后执行该函数
    var callback = function(){
            if (!called){
                fn();
                called=true;
            
    };
    elem.addEventListener(transitionEnd,function(){
        callback();
        //通过setTimeout来补救windowphone中不触发事件的问题
        setTimeout(callback,duration);
    },false);      
};

      通过这个函数函数,就可以解决了transitioned事件多次执行的问题,达到我们想要的目的,这时候把这段函数加到上面的代码中(为了配合本示例,将called的变量放到函数外面),运行下面的代码:

<!DOCTYPE html><html lang="en"><head><meta charset="UTF-8"><meta name="viewport" content="width=device-width,minimum-scale=1.0,maximum-scale=1.0"/><title>transitionend - 蜗牛博客(wnworld.com)</title><link rel="stylesheet" type="text/css" href="http://wnworld.com/wp-content/themes/temp1/css/reset.css"></head><body><style type="text/css">.movebox{width:50px;height:50px;position: relative;background:#f60;-webkit-transition-duration: 1s;-o-transition-duration: 1s;transition-duration: 1s;-webkit-transition-timing-function: linear;-o-transition-timing-function: linear;transition-timing-function: linear;}</style><div class="movebox" id="J_movebox"></div><div class="handguide-btn fixed align-c "><a href="javascript:void(0)" class="wn-btn wn-btn-success" id="J_movingbtn">&nbsp;&nbsp;运动&nbsp;&nbsp; </a> <a href="javascript:void(0)" class="wn-btn wn-btn-success" id="J_returnbeginbtn">&nbsp;&nbsp;恢复&nbsp;&nbsp; </a> </div><script type="text/javascript">var movebox=document.getElementById("J_movebox"),btn=document.getElementById("J_movingbtn"),returnbeginbtn=document.getElementById("J_returnbeginbtn"),i=0,transition="transition",body=document.body || document.documentElement,style=body.style;vartransitionEnd=(function(){var transEndEventNames = {      WebkitTransition : 'webkitTransitionEnd',      MozTransition    : 'transitionend',      OTransition      : 'oTransitionEnd otransitionend',      transition       : 'transitionend'    }for(var name in transEndEventNames){if(typeof style[name] === "string"){return transEndEventNames[name]}}})();var vendorPrefix=(function(){var i=0, vendor=["Moz", "Webkit", "Khtml", "O", "ms"];transition=transition.charAt(0).toUpperCase() + transition.substr(1);   while (i < vendor.length) {if (typeof style[vendor[i] + transition] === "string") {  return vendor[i];}i++;}return false;})();var called=false;var handleTransitionEndEvent=function(elem,fn,duration){//在每次transitionEnd的事件后执行该函数var callback = function(){if (!called){fn();called=true;}};elem.addEventListener(transitionEnd,function(){callback();setTimeout(callback,duration);},false);};function transitionEndFn(){ i++;alert("执行了"+transitionEnd+"事件"+i+"次");};handleTransitionEndEvent(movebox,transitionEndFn,"1s");btn.onclick=function(){i=0;called=false;movebox.style.width="150px";movebox.style.height="150px";movebox.style.backgroundColor="#000";movebox.style[vendorPrefix+"Transform"]="translate(100px,100px) rotate(45deg)";movebox.style[vendorPrefix+"TransitionProperty"]="width,height,background-color,transform";}returnbeginbtn.onclick=function(){i=0;called=false;movebox.style.width="50px";movebox.style.height="50px";movebox.style.backgroundColor="#f60";movebox.style[vendorPrefix+"Transform"]="translate(0px,0px) rotate(0deg)";movebox.style[vendorPrefix+"TransitionProperty"]="width,height,background-color,transform";}</script></body></html>
运行

      结果每次效果过渡完后,只执行了一次transtionend的事件!关于transitonend的jquery的处理方式,可以参考Bootstrap中的transition.js的处理方式。

二、animationend事件

      1.animationend浏览器支持情况:

03

      animationend的事件只有两种形式:animationend和WebkitAnimationEnd(注意事件名称的大小写)

      2.animationend事件执行次数:

      不同于transitionend事件,animationend只会在动画完成后执行一次:

<!DOCTYPE html><html lang="en"><head><meta charset="UTF-8"><meta name="viewport" content="width=device-width,minimum-scale=1.0,maximum-scale=1.0"/><title>动画</title><link rel="stylesheet" type="text/css" href="http://wnworld.com/wp-content/themes/temp1/css/reset.css"><script src="http://libs.baidu.com/jquery/1.10.0/jquery.js"></script><script type="text/javascript" src="plugin.js"></script><style type="text/css">.movebox{width:100px;height:100px;border:1px solid #5d5d5d;background: #f60;overflow:hidden;margin:10px;-webkit-animation-duration:1s ;-o-animation-duration:1s ;animation-duration:1s ;}@keyframes mymove{0%{-webkit-transform: translate(0px,0px);-moz-transform: translate(0px,0px);-ms-transform: translate(0px,0px);transform: translate(0px,0px);}100%{-webkit-transform: translate(100px,100px);-moz-transform: translate(100px,100px);-ms-transform: translate(100px,100px);transform: translate(100px,100px);}}@-webkit-keyframes mymove{0%{-webkit-transform: translate(0px,0px);-moz-transform: translate(0px,0px);-ms-transform: translate(0px,0px);transform: translate(0px,0px);}100%{-webkit-transform: translate(100px,100px);-moz-transform: translate(100px,100px);-ms-transform: translate(100px,100px);transform: translate(100px,100px);}}</style></head><body><div class="movebox" id="J_movebox"></div><div class="handguide-btn fixed align-c "><a href="javascript:void(0)" class="wn-btn wn-btn-success" id="J_movingbtn">&nbsp;&nbsp;运动&nbsp;&nbsp; </a> </div><script type="text/javascript">var movebox=document.getElementById("J_movebox"),btn=document.getElementById("J_movingbtn"),transition="transition",body=document.body || document.documentElement,style=body.style;var vendorPrefix=(function(){var i=0, vendor=["Moz", "Webkit", "Khtml", "O", "ms"];transition=transition.charAt(0).toUpperCase() + transition.substr(1);   while (i < vendor.length) {if (typeof style[vendor[i] + transition] === "string") {  return vendor[i];}i++;}return false;})();var animationEnd=(function(){if(vendorPrefix=="Webkit"){return "webkitAnimationEnd";}else{return "animationend";}}());movebox.addEventListener(animationEnd,function(){alert("执行了"+animationEnd+"事件!");movebox.style[vendorPrefix+"AnimationName"]="";},false)btn.onclick=function(){movebox.style[vendorPrefix+"AnimationName"]="mymove";}</script></body></html>
运行

理解transtionend和animationend两个事件,主要是在浏览器的前缀上面,搞清楚了这东西,做起来就比较得心应手了!

转载于http://wnworld.com/archives/191.html


原创粉丝点击