平时在做动画的时候,如果涉及交互比较多一些的时候。比如像拆礼盒,摇筛子等基于微信的小游戏,transitionend和animationend这个两个事件都会用到,之前做微信的小游戏过程中,把两个事件在pc端和移动端的常用的浏览器给测试了一下并做了整理,虽然浏览器的支持结果大同小异,但是还是有一些细微的差别的,其中微信和qq浏览器(其实是同一个)对于两个事件都需要加前缀!
一、transitionend事件
1.浏览器支持情况
注:transitionend的事件只有三种形式,之所以不检测MozTransitionEnd,msTransitionEnd 这两个的事件,因为火狐和IE都已经支持了transitionend,相反的对于加前缀反而不执行事件,oTransitionEnd 代表的是欧朋浏览器,transitionend 一定要小写 否则浏览器不识别,webkitTransitionEnd中T和E是一定要大写的,w大小写是无所谓的!
2.transitionend有过渡效果的css属性
为什么要知道有过渡css属性的呢?首先是,实例运用中,经常会发现,一个元素起始时的display:none,想通过transition来实现动画过渡效果,结果发现不行,因为display没有过渡效果! 其次,有过渡的css属性决定了transtionend的执行次数(下面会说),在transitionDuration的时间不为0的时候,有过渡效果的css属性,也就transition-property支持的css的属性有:
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"> 运动 </a> <a href="javascript:void(0)" class="wn-btn wn-btn-success" id="J_returnbeginbtn"> 恢复 </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; var transitionEnd=(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.οnclick=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.οnclick=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"> 运动 </a> <a href="javascript:void(0)" class="wn-btn wn-btn-success" id="J_returnbeginbtn"> 恢复 </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; var transitionEnd=(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.οnclick=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.οnclick=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浏览器支持情况:
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"> 运动 </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.οnclick=function(){ movebox.style[vendorPrefix+"AnimationName"]="mymove"; } </script> </body> </html>
理解transtionend和animationend两个事件,主要是在浏览器的前缀上面,搞清楚了这东西,做起来就比较得心应手了!
转载于http://wnworld.com/archives/191.html