原生js判斷css3動畫過分(transition)結束 transitionend事件

原生js判斷css3動畫過分(transition)結束 transitionend事件 以及關鍵幀keyframes動畫結束(animation)回調函數 animationEnd 以及 css 過渡 transition無效

 

 

上圖的 demo 主要講的 是 css transition的過渡回調函數transitionend事件;javascript

 

css3 的時代,css3--動畫 一切皆有可能;css

 

傳統的js 能夠經過回調函數判斷動畫是否結束;即便是採用CSS技術生成動畫效果,JavaScript仍然能捕獲動畫或變換的結束事件;html

transitionend事件和animationend事件標準的瀏覽器事件,但在WebKit瀏覽器裏你仍然須要使用webkit前綴,因此,咱們不得不根據各類瀏覽器分別檢測事件java

1
2
3
4
5
6
var  transitions = {
        'transition' : 'transitionend' ,
        'OTransition' : 'oTransitionEnd' ,
        'MozTransition' : 'transitionend' ,
        'WebkitTransition' : 'webkitTransitionEnd'
      }

 

下面附上源代碼:css3

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
<!doctype html>
<html>
<head>
<meta charset= "utf-8" >
<title>suface   js判斷css動畫是否結束</title>
</head>
 
<body>
 
<p>一旦動畫或變換結束,回調函數就會觸發。再也不須要大型類庫支持。<br> </p>
<style type= "text/css" >
.sample {
width: 200px;
height: 200px;
border: 1px solid green;
background: lightgreen;
opacity: 1;
margin-bottom: 20px;
transition-property: opacity;
/*transition-duration: .5s;*/
transition-duration:3s;
}
.sample.hide {
opacity: 0;
}
</style>
<div class = "sample" >css3動畫過分慢慢隱藏(transition-duration:3s;)</div>
<p><button onclick= "this.style.display='none';startFade();" >慢慢消退,檢測結束事件</button></p>
<script>            
  ;( function () {
    var  e = document.getElementsByClassName( 'sample' )[0];
    function  whichTransitionEvent(){
    var  t,
        el = document.createElement( 'surface' ),
        transitions = {
          'transition' : 'transitionend' ,
          'OTransition' : 'oTransitionEnd' ,
          'MozTransition' : 'transitionend' ,
          'WebkitTransition' : 'webkitTransitionEnd'
        }
 
        for (t in  transitions){
            if ( el.style[t] !== undefined ){
                return  transitions[t];
            }
        }
    }
 
    var  transitionEvent = whichTransitionEvent();
    transitionEvent && e.addEventListener(transitionEvent, function () {
     alert( 'css3運動結束!我是回調函數,沒有使用第三方類庫!' );
                                 e. removeEventListener(transitionEvent,arguments.callee, false ); //銷燬事件
                                 
    });
 
    startFade = function () {
     e.className+= ' hide' ;
    }
   })();
</script>
</body>
</html><br><br> //兼容性 詳情

另外,注意一下:在js調用中;transitionend 存幾個個問題:web

若是 transition 中:變換的屬性有多個 ;好比設置寬高 過分(transition :width:.2s,height:.2s), transitionend  事件會促發2次json

 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
<style>
.surfaces_box{ background:url(../../loveImg/QioA-fxehfqi8208393.jpg) no-repeat center center;;width:550px;;height:343px;; margin:0 auto; position: relative;}
.surfaces_box p{ position:absolute; bottom:0; left:0; right:0; color: #333; text-align:center; padding:10px 0; background: rgba(255,255,255,.4) }
.surfaces{width:100px;height:100px;background:red;  color: #fff; text-align:center; transition:width 1s ,height 1s;}
 
</style>
 
 
<div  class = "surfaces_box" >
    <div  class = "surfaces"  id= "j_surfaces" >click me </div>
    <p>http: //www.cnblogs.com/surfaces/</p>
</div>
<script>
function  addEnd(obj,fn){
     obj.addEventListener( 'WebkitTransitionEnd' ,fn, false );
     obj.addEventListener( 'transitionend' ,fn, false );
}
 
var  surfaces=document.getElementById( "j_surfaces" );
surfaces.onclick= function (){
     this .style.width= this .offsetWidth+100+ "px" ;
     this .style.height= this .offsetHeight+100+ "px" ;
};
 
 
addEnd(surfaces, function (){
     alert( 'CSS3 過渡結束回調 ' );
});
 
</script>

  

 

若是 transition 中:變換的屬性 (transition :width:.1s);transitionend 以後再次改變 寬度; 再次促發 transition相似遞歸;api

 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
<style>
.surfaces_box{ background:url(../../loveImg/QioA-fxehfqi8208393.jpg) no-repeat center center;;width:550px;;height:343px;; margin:0 auto; position: relative;}
.surfaces_box p{ position:absolute; bottom:0; left:0; right:0; color: #333; text-align:center; padding:10px 0; background: rgba(255,255,255,.4) }
.surfaces{width:100px;height:100px;background:red;  color: #fff; text-align:center; transition:width 1s}
 
</style>
 
 
<div  class = "surfaces_box" >
    <div  class = "surfaces"  id= "j_surfaces" >click me </div>
    <p>http: //www.cnblogs.com/surfaces/</p>
</div>
<script>
function  addEnd(obj,fn){
     obj.addEventListener( 'WebkitTransitionEnd' ,fn, false );
     obj.addEventListener( 'transitionend' ,fn, false );
}
 
var  surfaces=document.getElementById( "j_surfaces" );
surfaces.onclick= function (){
     this .style.width= this .offsetWidth+100+ "px" ;
};
 
 
addEnd(surfaces, function (){
     this .style.width= this .offsetWidth+100+ "px" ;
     alert( 'CSS3 過渡結束回調 ' );
});
 
</script>

  

 

若是元素原先display:none  到block,transition 過渡無效;可能致使transitionend 失效;舉個例子 dom元素從display:none 到block ,dom的opacity從0到1的 transition沒過渡 ;瀏覽器

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
<style>
.surfaces_box{ background:url(../../loveImg/QioA-fxehfqi8208393.jpg) no-repeat center center;;width:550px;;height:343px;; margin:0 auto; position: relative;}
.surfaces_box p{ position:absolute; bottom:0; left:0; right:0; color: #333; text-align:center; padding:10px 0; background: rgba(255,255,255,.4) }
.surfaces{width:100px;height:100px;background:red;  color: #fff; text-align:center; transition:width 1s}
.surfaces_box .hideElement{width:100px;height:100px; position:absolute; right:0; top:0; background:red;  color: #fff; text-align:center; transition:opacity 1s; display:none; opacity:0;}
</style>
 
 
<div  class = "surfaces_box" >
    <div  class = "surfaces"  id= "j_surfaces" >click me </div>
    
    <div   class = "hideElement"  id= "j_hideElement" >opacity  transition</div>
    
    <p>http: //www.cnblogs.com/surfaces/</p>
</div>
<script>
 
var  j_hideElement=document.getElementById( "j_hideElement" );
var  surfaces=document.getElementById( "j_surfaces" );
surfaces.onclick= function (){
     j_hideElement.style.display= 'block' //// 原先display=none
     j_hideElement.style.opacity=1;  // transition:opacity 1s;
};
 
</script>

  

 

上圖 dom元素 從none到block,致使 transition-duration 沒法渲染; css3動畫

1 通常是這樣解決 加個計時器延遲  

 

2 或者 強制 /強制 獲取當前的內聯樣式

3或者重繪

 

都是從none到block ,dom元素剛生成未能即便渲染,致使過分失效,因此主動觸發頁面迴流(重繪),刷新DOM;

更改 offsetTop、offsetLeft、 offsetWidth、offsetHeight;scrollTop、scrollLeft、scrollWidth、scrollHeight;clientTop、clientLeft、clientWidth、clientHeight;getComputedStyle() 、currentStyle()。這些都會觸發迴流。迴流致使DOM從新渲染,平時要儘量避免,但這裏,爲了動畫即時生效播放,則主動觸發迴流,刷新DOM。

 

4 另外 部分低端安卓機型或者wp手機  沒法促發 transitionend事件 須要主動觸發一次

 

以上綜合解決方式大體以下;

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
var  fired =  false ;
var  handler =  function  () { //回調函數中解綁事件
 
          callback && callback.apply(obj,arguments);
          fired= true ;
            
          obj.removeEventListener(transitionEnd,arguments.callee, false )            
};
    
   if (obj.addEventListener){
    obj.addEventListener(transitionEnd, handler, false );
   }
  
 
  setTimeout( function (){ //綁定過事件還作延時處理,是transitionEnd在older Android phones不必定觸發
         if (fired)  return
           handler()
},(duration + delay) + 25);

  

咱們進行封裝一下;封裝後的直接調用以下;參考zepto 改寫;不依賴任何類庫,詳情源碼調用例子 點擊transform.js  查看;該函數兼容性與zepto一致;

transform(dom元素,{ css屬性:css值},transitionDuration(單位:毫秒),transitionTiming,transitionend回調函數,transitionDelay(單位:毫秒));

transform(dom元素,keyframesName,animationDuration,animationTiming,animationend回調函數,animationDelay(單位:毫秒));

參數說明: 

複製代碼
/*
* js transfrom.js
* @param obj {obj}    原生dom對象
* @param properties  {json} ||string     { translate3d:'220px,10px,0',left:'1em',opacity:0.2, rotateY:'30deg'} || animationName 多個能夠以逗號分割 如 'fadeIn,sliderDown';
* @param duration {number}    默認400毫秒 可省略
* @param ease {str}           默認linear,可省略  支持  cubic-bezier(0.42,0,1,1)寫法;
* @param callback {function}    回調函數   可省略
* @param delay {number}    延遲時間    可省略
 
*/
複製代碼

多種參數 調用寫法示例:

複製代碼
/* http://www.cnblogs.com/surfaces

   * @param properties 爲 {} 或者 string ;若是 properties= string 爲animation- name   
   
    * transform(elem, properties)
    * transform(elem, properties, ease)
    * transform(elem, properties, ease, delay)
    * transform(elem, properties, ease, callback, delay)
    * transform(elem, properties, callback)
    * transform(elem, properties, callback, delay)
    * transform(elem, properties, duration )
    * transform(elem, properties, duration, ease)
    * transform(elem, properties, duration, delay)
    * transform(elem, properties, duration, callback)    
    * transform(elem, properties, duration, callback,delay)   
    * transform(elem, properties, duration, ease, delay)
    * transform(elem, properties, duration, ease, callback)   
    * transform(elem, properties, duration, ease, callback,delay)

    //使用示例以下:
    transform(elem,{translateX:'150px',left:'1em',opacity:0.2,perspective:'400px', rotateY:'40deg'},600,'linear',
      function(){  console.log('transition結束回調') },200) ; 

    transform(elem, keyframesName,600,'linear',function(){  console.log('animation結束回調') },200) ; 
*/
複製代碼

 

不要搞混css3動畫事件 webkitAnimationEnd 事件

至於animation關鍵幀動畫結束,提供了3個api;以下

開始事件 webkitAnimationStart 
結束事件 webkitAnimationEnd 
重複運動事件 webkitAnimationIteration;

 

1
本文地址:<a href= "http://www.cnblogs.com/surfaces/"  target= "_blank" >http://www.cnblogs.com/surfaces/</a>

 

 

總結:

  相同點:

  二者都在移動端大放光彩;利用GPU加速性能,相對流暢;

  利用  js進行對動畫結束事件能夠捕捉監聽;

 

  區別之處

  transition 只有惟一的事件 transitionend,而animation 有3個;

  transition 強調過渡,Transition + Transform = 兩個關鍵幀的Animation

  animation 強調流程與控制,Duration + TransformLib + Control = 多個關鍵幀的Animation

  animation 能夠實時捕捉操做修改屬性,  而transition沒法捕捉 中間過程;

  transition 每每須要事件驅動,hover,click之類 促發,animation從flash延伸出來

相關文章
相關標籤/搜索