• 原生js判断css3动画过度(transition)结束 transitionend事件 以及关键帧keyframes动画结束(animation)回调函数 animationEnd 以及 css 过渡 transition无效


     

    上图的 demo 主要讲的 是 css transition的过渡回调函数transitionend事件;

    css3 的时代,css3--动画 一切皆有可能;

    传统的js 可以通过回调函数判断动画是否结束;即使是采用CSS技术生成动画效果,JavaScript仍然能捕获动画或变换的结束事件;

    transitionend事件和animationend事件标准的浏览器事件,但在WebKit浏览器里你仍然需要使用webkit前缀,所以,我们不得不根据各种浏览器分别检测事件

      var transitions = {
    			      'transition':'transitionend',
    			      'OTransition':'oTransitionEnd',
    			      'MozTransition':'transitionend',
    			      'WebkitTransition':'webkitTransitionEnd'
    			    }

    下面附上源代码:

    <!doctype html>
    <html>
    <head>
    <meta charset="utf-8">
    <title>suface   js判断css动画是否结束</title>
    </head>
    
    <body>
    
    <p>一旦动画或变换结束,回调函数就会触发。不再需要大型类库支持。<br> </p>
    <style type="text/css">
    .sample {
     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>

    //兼容性 详情

    另外,注意一下:在js调用中;transitionend 存几个个问题:

    如果 transition 中:变换的属性有多个 ;比如设置宽高 过度(transition :.2s,height:.2s), transitionend  事件会促发2次

     

    <style>
    .surfaces_box{ background:url(../../loveImg/QioA-fxehfqi8208393.jpg) no-repeat center center;;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{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 :.1s);transitionend 之后再次改变 宽度; 再次促发 transition类似递归;

    <style>
    .surfaces_box{ background:url(../../loveImg/QioA-fxehfqi8208393.jpg) no-repeat center center;;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{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没过渡 ;

    <style>
    .surfaces_box{ background:url(../../loveImg/QioA-fxehfqi8208393.jpg) no-repeat center center;;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{100px;height:100px;background:red;  color:#fff; text-align:center; transition:width 1s}
    .surfaces_box .hideElement{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 无法渲染; 

    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事件 需要主动触发一次

     

    以上综合解决方式大致如下;

            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;

    本文地址:http://www.cnblogs.com/surfaces/

    总结:

      相同点:

      两者都在移动端大放光彩;利用GPU加速性能,相对流畅;

      利用  js进行对动画结束事件可以捕捉监听;

      区别之处

      transition 只有唯一的事件 transitionend,而animation 有3个;

      transition 强调过渡,Transition + Transform = 两个关键帧的Animation

      animation 强调流程与控制,Duration + TransformLib + Control = 多个关键帧的Animation

      animation 可以实时捕捉操作修改属性,  而transition无法捕捉 中间过程;

      transition 往往需要事件驱动,hover,click之类 促发,animation从flash延伸出来

  • 相关阅读:
    NDOC中文支持及入门用法
    网页代码常用小技巧
    SOCKET通讯点滴
    自动备份程序目录
    MySql.Data.dll Microsoft.Web.UI.WebControls.dll下载
    c#:获取IE地址栏中的URL
    比较好的单例登录模式(参考网友)
    FreeTextBox使用详解
    2005自定义控件显示基准线
    连接字符串大全
  • 原文地址:https://www.cnblogs.com/surfaces/p/4324044.html
Copyright © 2020-2023  润新知