• 移动端 transition动画函数的封装(仿Zepto)以及 requestAnimationFrame动画函数封装(仿jQuery)


     

    移动端 css3 transition 动画 ,requestAnimationFrame 动画  对于性能的要求,h5优先考虑;

    移动端 单页有时候 制作只用到简单的css3动画即可,我们封装一下,没必要引入zepto框架,把zepto的动画模块从Zepto 扒下来,加以改造独立;用于生产环境;下面是 Demo栗子;

    上面图片对应的 js

             var leftsbox=document.getElementById("leftsbox");
    	  var boxdiv=leftsbox.getElementsByTagName("div");
    	  leftsbox.onclick=function(){
    		   for(var i=0;i<boxdiv.length;i++){
    			         var that=boxdiv[i];
    			 			 transform(that,{ translate3d:'220px,10px,0',left:'1em',opacity:0.2,perspective:'400px', rotateY:'30deg'},800,'cubic-bezier(0.15, 0.5, 0.25, 1.0)',function(){
    							   this.innerHTML='结束回调'+this.innerHTML;
    						},100*i);
    			} //for
    

      

    再看看另外一种 常见的 如下图

    上面对用的 js 代码

      
                           var nav=document.querySelector(".nav");
    			var nava=nav.getElementsByTagName("li");
    			var content=document.querySelector(".content");
    			var ulcontent=document.getElementById("ulcontent");
    			ulcontent.style.width=nav.offsetWidth*nava.length+'px';
    			for(var i=0;i<nava.length;i++) {
    				nava[i].index=i;
    				nava[i].onclick=function(){
    					var that=this;
    					var now=-(that.index)*content.offsetWidth+'px';
    
    					 transform(ulcontent,{translate3d:''+now+',0,0',},'linear',function(){
    					//console.log('success   回调函数');
    					})
    				}//click end
    			}
    

      htm结构

     <ul class="nav">
    	        <li ><a >首页</a></li>
    	        <li ><a >插件</a></li>
    	        <li ><a >新闻</a></li>
    	        <li ><a >其他</a></li>
    	    </ul>
       
         <div class="content">
            <ul id="ulcontent" >
            <li ><img src="../../images/1a.jpg"></li>
            <li ><img src="../../images/2a.jpg"></li>
            <li ><img src="../../images/3a.jpg"></li>
            <li style="background:#ddd;" >44444444444</li>
            </ul>
         </div>
    

      

    基于zepto动画独立出来,原先zepto 动画书写方式

    $("#banners").animate(
        {
            translate3d:'220px,10px,0',
    		left:'1em',
    		opacity:0.2,
    		perspective:'400px', 
    		rotateY:'30deg'
        },
        800,
       'cubic-bezier(0.15, 0.5, 0.25, 1.0)',
        function(){  alert('回调'); },
       1000    
    )
    

      

    改写后 独立与zepto的 动画函数 语法如下 

    transform(dom元素,{ transitionProperty:css值},transitionDuration(单位:毫秒),transitionTiming,transitionend回调,transitionDelay(单位:毫秒)); 

    transform(dom元素,animationName,animationDuration(单位:毫秒),animationTiming,animationend回调,animationDelay(单位:毫秒)); 

    /*
    * js transfrom
    * @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}      css3持续时间 秒 默认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, rotateY:'40deg'},600,'linear',function(){  console.log('结束回调') },200) ; 
    
        transform(elem, keyframesName,600,'linear',function(){  console.log('结束回调') },200) ; 
    */
    

      

        

    关于兼容性:几乎与zepto一致 ,也支持 动画帧 keyframe,个人觉得  keyframe移动端 兼容性不是很好,尤其手机自带的浏览器(原生app 调用 内嵌H5页面,小问题还是蛮多的),适合无关dom数据操作,只显示美化用;

     另外,我们需要了解下  css3 transition-duration的属性写法有多种;如下

    1). 过渡单个属性:

     transition-property:opacity;
    transition-duration:2s;
    transition-timing-function:ease-in;
    transition-delay:0;
    

      

    2). 过渡多个属性:
    [1]. 上下一一对应型:
     

    transition-property:opacity left;
    transition-duration:2s, 4s;
    transition-timing-function:ease-in;
    transition-delay:0;
    

      

    此时:opacity过渡时间为2s,left过渡时间为4s。

    [2]. 循环对应型:
     

    transition-property:opacity left width height;
    transition-duration:2s, 4s;
    transition-timing-function:ease-in;
    transition-delay:0;
    

      

    此时:opacity和width过渡时间为2s,left和height过渡时间为4s。

    3). transition简写模式:
    顺序为:transition-property transition-duration transition-timing-function transition-delay


      /*单个属性:*/
    -moz-transition:background 0.5s ease-out 0s;
    /*多个属性:*/
    -moz-transition:background, 0.5s ease-out 0s, color 0.4 ease-out 0s;

     

     过渡持续时间
    transition-duration 属性规定了一个过渡从初始状态到目标状态的持续时间。它接受以秒或毫秒的值(例如,2.3S和2300ms都是指2.3秒)。
    尽管规范明确规定了过渡值必须为正数,但 Opera 仍接受-5S的值,至少对于getComputedStyle()来说是这样的。虽然规范中并没有限制属性值的大小,但 Opera 和 IE 不接受低于10ms的值。而 WebKit 在 getComputedStyle()执行中有个小bug,例如:返回值0.009999999776482582s会取代0.01s。

    过渡延迟时间
    transition-delay 属性规定了在执行一个过渡之前的等待时间,同样使用值。Delay 可以是负值,但这会导致动画无法平滑过渡。
    IE 和 Opera 不接受 transition-duration 在-10ms和10ms之间的值。WebKit 的 floating point 也会在这儿出现。

    http://www.cnblogs.com/surfaces/ 

    另外属性相似点 animation-name:keyfrmaes1,keyfrmaes2;以逗号分割;

     其他的

    zepto核心动画但是实现了大部分常用的动画;在阅读器zepto核心动画源码的 时候,自己手动封装 实践;就机会发现 看似读懂其实不懂;自己正真封装调试后;才发现哪些巧;

     

    封装后的   transform.js  源码如下

     参数说明

    /*
    * js transfrom
    * @param obj {obj}    原生dom对象
    * @param properties  {json} || string     { translate3d:'220px,10px,0',left:'1em',opacity:0.2,perspective:'400px', rotateY:'30deg'} ||animation-name
    * @param duration {number}      css3持续时间 秒 默认400毫秒
    * @param ease {str}         transition-timing-function  默认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('结束回调') },200) ; 
        transform(elem, keyframesName,600,'linear',function(){  console.log('结束回调') },200) ; 
    */
    

     移动端 transform.js 源码如下;双击直接复制即可; 

    ;(function(window,document,undefined){var prefix=function(){var div=document.createElement("div");var cssText="-webkit-transition:all .1s;-moz-transition:all .1s; -Khtml-transition:all .1s; -o-transition:all .1s; -ms-transition:all .1s; transition:all .1s;";div.style.cssText=cssText;var style=div.style;var dom="";if(style.webkitTransition){dom="webkit"}else{if(style.MozTransition){dom="moz"}else{if(style.khtmlTransition){dom="Khtml"}else{if(style.oTransition){dom="o"}else{if(style.msTransition){dom="ms"}}}}}div=null;if(dom){return{dom:dom,lowercase:dom,css:"-"+dom+"-",js:dom[0].toUpperCase()+dom.substr(1)}}else{return false}}();var transitionEnd=function(){var el=document.createElement("div");var transEndEventNames={WebkitTransition:"webkitTransitionEnd",MozTransition:"transitionend",OTransition:"oTransitionEnd",msTransition:"MSTransitionEnd",transition:"transitionend"};for(var name in transEndEventNames){if(el.style[name]!==undefined){return transEndEventNames[name]}}el=null;return false}();var animationEnd=(function(){var eleStyle=document.createElement("div").style;var verdors=["a","webkitA","MozA","OA","msA"];var endEvents=["animationend","webkitAnimationEnd","animationend","oAnimationEnd","MSAnimationEnd"];var animation;for(var i=0,len=verdors.length;i<len;i++){animation=verdors[i]+"nimation";if(animation in eleStyle){return endEvents[i]}}return"animationend"}());var supportedTransforms=/^((translate|rotate|scale)(X|Y|Z|3d)?|matrix(3d)?|perspective|skew(X|Y)?)$/i;var dasherize=function(str){return str.replace(/::/g,"/").replace(/([A-Z]+)([A-Z][a-z])/g,"$1_$2").replace(/([a-zd])([A-Z])/g,"$1_$2").replace(/_/g,"-").toLowerCase()};function transform(obj,properties,duration,ease,callback,delay){if(!obj){return}if(typeof duration=="undefined"){duration=400;ease="linear";callback=undefined;delay=undefined}if(typeof duration=="string"){if(typeof ease=="number"){delay=ease;callback=undefined}if(typeof ease=="function"){delay=callback;callback=ease}ease=duration;duration=400}else{if(typeof duration=="function"){if(typeof ease=="number"){delay=ease}callback=duration;duration=400;ease="linear"}else{if(typeof duration=="number"){if(typeof ease=="undefined"){ease="linear"}else{if(typeof ease=="string"){ease=ease}else{if(typeof ease=="function"){if(typeof callback=="number"){delay=callback}callback=ease;ease="linear"}else{if(typeof ease=="number"){delay=ease;ease="linear"}}}}if(typeof callback=="number"){delay=callback;callback=undefined}}}}delay=(typeof delay=="number")?delay:0;var endEvent=transitionEnd;var nowTransition=prefix.js+"Transition";var nowTransform=prefix.js+"Transform";var prefixcss=prefix.css;if(!prefix.js){nowTransition="transition";nowTransform="transform";prefixcss=""}var transitionProperty,transitionDuration,transitionTiming,transitionDelay;var animationName,animationDuration,animationTiming,animationDelay;var key,cssValues={},cssProperties,transforms="";var transform;var cssReset={};var css="";var cssProperties=[];transform=prefixcss+"transform";cssReset[transitionProperty=prefixcss+"transition-property"]=cssReset[transitionDuration=prefixcss+"transition-duration"]=cssReset[transitionTiming=prefixcss+"transition-timing-function"]=cssReset[transitionDelay=prefixcss+"transition-delay"]=cssReset[animationName=prefixcss+"animation-name"]=cssReset[animationDuration=prefixcss+"animation-duration"]=cssReset[animationTiming=prefixcss+"animation-timing-function"]=cssReset[animationDelay=prefixcss+"animation-delay"]="";if(typeof properties=="string"){cssValues[animationName]=properties;cssValues[animationDuration]=duration+"ms";cssValues[animationTiming]=(ease||"linear");cssValues[animationDelay]=(delay)+"ms";endEvent=animationEnd}else{endEvent=transitionEnd;for(key in properties){if(supportedTransforms.test(key)){transforms+=key+"("+properties[key]+") "}else{cssValues[key]=properties[key],cssProperties.push(dasherize(key))}}if(transforms){cssValues[transform]=transforms,cssProperties.push(transform)}if(duration>0&&typeof properties==="object"){cssValues[transitionProperty]=cssProperties.join(", ");cssValues[transitionDuration]=duration+"ms";cssValues[transitionTiming]=(ease||"linear");cssValues[transitionDelay]=(delay)+"ms"}}for(var attr in cssValues){css+=dasherize(attr)+":"+cssValues[attr]+";"}obj.style.cssText=obj.style.cssText+";"+css;obj.clientLeft;if(!callback){return}var fired=false;var handler=function(event){if(typeof event!=="undefined"){if(event.target!==event.currentTarget){fired=true;return}}callback&&callback.apply(obj,arguments);fired=true;obj.removeEventListener(endEvent,arguments.callee,false)};if(obj.addEventListener){obj.addEventListener(endEvent,handler,false)}if(!endEvent||duration<=0){setTimeout(function(){handler()});return}setTimeout(function(){if(fired){return}handler()},parseInt((duration+delay)+25))}window.transform=transform})(window,document);
    

     部分示例 使用代码

     

    <style>
    *{ margin:0; padding:0;}
    ul,li{ list-style:none; margin:0; padding:0;}
    
    html{-webkit-touch-callout:none;-webkit-user-select:none;-webkit-text-size-adjust:100%;-webkit-tap-highlight-color:transparent; font-size:62.5%; }
    body{ font-size:14px;}
    
    	  
    #leftsbox{ 88%; height:auto; overflow:hidden; border:2px solid red; margin:0 auto; padding:30px 0;}
    #leftsbox div{ 80px; height:80px; background:#6C6; margin-bottom:10px; position:relative; left:0; backface-visibility:hidden;  
    -webkit-animation-fill-mode:forwards; 
    	animation-fill-mode:forwards;
    }
    
    @keyframes keyframesName{
    	0%{ transform:translateX(0)}
    	100%{transform:translateX(600px) }
    }
    @-webkit-keyframes keyframesName{
    	0%{ -webkit-transform:translateX(0)}
    	100%{-webkit-transform:translateX(600px) }
    }
    
        </style>
        <div id="leftsbox">
          <div class="leftssa" style="background:red">1 lefts 22   RAF</div>
          <div class="leftssa " style="120px; background:#FF0">2 lefts 22   RAF</div>
          <div class="leftssa"> 333lefts 22   RAF</div>
        </div>
        
    <script>
    
    	  var leftsbox=document.getElementById("leftsbox");
    	  var boxdiv=leftsbox.getElementsByTagName("div");
    	  leftsbox.onclick=function(e){
    		 
    		   for(var i=0;i<boxdiv.length;i++){
    			         var that=boxdiv[i];
    			 // transform(that,{ translate3d:'220px,10px,0',left:'1em',opacity:0.2,perspective:'400px', '200px', rotateY:'30deg'},800,'cubic-bezier(0.15, 0.5, 0.25, 1.0)',function(){
    				//  this.innerHTML='结束回调'+this.innerHTML;
    			// },1000*i);
    						
    						
                        /*   properties json(css3 属性)  或者 string(css3动画名称)
    				      * 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)
                         */
    					 
    					 //测试 properties为 keyframes
    					 var keyframes='keyframesName';
    					 //transform(that, keyframes) 
    					 //transform(that, keyframes,'ease') 
    					 //transform(that, keyframes,'ease',1000*i) 
    					 //transform(that, keyframes,'ease',function(){ this.innerHTML='结束回调'+this.innerHTML;},1000*i) 
    					
    					//transform(that, keyframes,function(){ this.innerHTML='结束回调'+this.innerHTML;})
    					//transform(that, keyframes,function(){ this.innerHTML='结束回调'+this.innerHTML;},1000*i) 
    					
    					//transform(that, keyframes,600)  
    					//transform(that, keyframes,600,ease') 
    					//transform(that, keyframes,600,1000*i) ;
    					//transform(that, keyframes,600,function(){ this.innerHTML='结束回调'+this.innerHTML;}) ;  
    					//transform(that, keyframes,600,function(){ this.innerHTML='结束回调'+this.innerHTML;},1000*i) ;
    					
    					//transform(that, keyframes,600,'ease',1000*i) 
    					// transform(that, keyframes,600,'ease',function(){ this.innerHTML='结束回调'+this.innerHTML;}) ;
    					// transform(that, keyframes,600,function(){ this.innerHTML='结束回调'+this.innerHTML;},1020*i) ; 
    					// transform(that, keyframes,600,function(){ this.innerHTML='结束回调'+this.innerHTML;},-20*i) ; //css3 animation-delay 支持负数 直接进入到时间点
    					
    					 //测试 properties为 Json
    					 var json={translate3d:'600px,10px,0',left:'1em',opacity:0.2,perspective:'400px', '200px', rotateY:'30deg'}
    					 //transform(that,json);
    					  // transform(that, json,'ease') 
    					 //transform(that, json,'ease',1000*i) 
    					 //transform(that, json,'ease',function(){ this.innerHTML='结束回调'+this.innerHTML;},1000*i) 
    					
    					//transform(that, json,function(){ this.innerHTML='结束回调'+this.innerHTML;})
    					//transform(that, json,function(){ this.innerHTML='结束回调'+this.innerHTML;},1000*i) 
    					
    					//transform(that, json,600)  
    					//transform(that, json,600,'ease') 
    					//transform(that, json,600,1000*i) ;
    					//transform(that, json,600,function(){ this.innerHTML='结束回调'+this.innerHTML;}) ;  
    					// transform(that, json,600,function(){ this.innerHTML='结束回调'+this.innerHTML;},1000*i) ;
    					
    					//transform(that, json,600,'ease',1000*i) 
    					//transform(that, json,600,'ease',function(){ this.innerHTML='结束回调'+this.innerHTML;}) ;
    					transform(that, json,600,'ease',function(){ this.innerHTML='结束回调'+this.innerHTML;},1000*i) ;
    					//transform(that, json,600,'ease',function(){ this.innerHTML='结束回调'+this.innerHTML;},-100*i) ; ////css3 transition-delay 支持负数 直接进入到时间点
    					
    					   
                } //for end
    		 
    	  }	  			
    </script>
    

      

    唯一的缺点  scrollTop 缓动不支持; 这里有个简易的  函数 类似jquery  语法几乎一样 基于时间 算法 使用 requestAnimationFrame  

    先看效果

    相关布局

    <ul id="inner" >
            <li><a class="on" >护肤</a></li>
            <li><a >彩妆</a></li>
            <li><a >洗护</a></li>
            <li><a >套装</a></li>
        </ul>
        
         <ul class="uls" id="uls">
            <li id='li1'></li>
             <li id='li12'></li>
             <li id='li3'></li>
      
     </ul>
    
        
        
     <div class="box22">
     <div class="boxs">1111111111111111111111111111111111</div>
      <div class="boxs">22222222222222222222222222222</div>
      
       <div class="boxs">33333333333333333333333</div>
      <div class="boxs" style="height:100px;">4444444444444444444最后一个 </div>
     </div>
     
     
     <div id="gpTop">tops</div>

    上图相关js

      document.getElementById("gpTop").onclick=function(e){
                  var  that=this;
                     startMove(that,{"scrollTop":0},function(){
                        that.innerHTML='到顶了';
                         });  // 206px; height: 101px; opacity: 0.3;
                    }
                    
                    
                    var inner=document.getElementById("inner");
                    var inlione=inner.getElementsByTagName("li");
                    var box=document.querySelectorAll(".boxs");
                    
                    for(var i=0;i<inlione.length;i++) {  
                     inlione[i].index=i;
                     inlione[i].onclick=function(e){
                     var that=this;
                    // console.log(that.index);
                     var box2=box[that.index];
                     var nowTop=getOffest(box2).top;
                    // console.log(nowTop);
                     
                      animate(window,{"scrollTop":nowTop},function(){
                        //console.log('success');
                        });
               }
                 
            }

    如果通过原生js  获取  jquey的offset().top  的值呢 如下  这里

      
    var getOffest=function (obj){
    var top=0,left=0;
    if(obj){
     while(obj.offsetParent){
          top += obj.offsetTop;
          left += obj.offsetLeft;
          obj = obj.offsetParent;
       }
     }
    
      return{
      top : top,
      left : left
      }
    }

    animate.js基于 requestAnimationFrame  兼容ie8+    (单位px  未做rem 兼容处理 ,没有jquery的 stop()处理)

    语法如下

     

    animate(dom元素,{"left":1300,"opacity":90},持续时间(毫秒),缓动形式(tween函数),回调函数);

    			  animate(element,{"left":1300,"opacity":90},2000,'easeOut',function sa(){
    			  console.log('回调函数');
    			 });  
    

     

    为什么要用   requestAnimationFrame  。

    浏览器可以优化并行的动画动作,更合理的重新排列动作序列,并把能够合并的动作放在一个渲染周期内完成,从而呈现出更流畅的动画效果。比如,通过requestAnimationFrame(),JS动画能够和CSS动画/变换或SVG SMIL动画同步发生。另外,如果在一个浏览器标签页里运行一个动画,当这个标签页不可见时,浏览器会暂停它,这会减少CPU,内存的压力,节省电池电量。

    相信日后  requestAnimationFrame 在移动端发展的前景是相当不错的,目前安卓上感觉还是有点丢帧。抖动明显;

    requestAnimationFrame  一个简单的例子

    var start = null;
    var ele = document.getElementById("j_precent");
    var progress = 0;
    
    function step() {
        progress += 1;
        ele.style.width = progress + "%";
        ele.innerHTML=progress + "%";
        if (progress < 100) {
            requestAnimationFrame(step);
        }
    }
    
    document.getElementById("btn_run").addEventListener("click", function() {
        ele.style.width = "1px";
        progress = 0;
         step()
    }, false);
    

      

    如下   jQuery1.6.2还用 requestAnimationFrame;

    // Start an animation from one number to another
    custom: function( from, to, unit ) {
        var self = this,
            fx = jQuery.fx,
            raf;
    
        this.startTime = fxNow || createFxNow();
        this.start = from;
        this.end = to;
        this.unit = unit || this.unit || ( jQuery.cssNumber[ this.prop ] ? "" : "px" );
        this.now = this.start;
        this.pos = this.state = 0;
    
        function t( gotoEnd ) {
            return self.step(gotoEnd);
        }
    
        t.elem = this.elem;
    
        if ( t() && jQuery.timers.push(t) && !timerId ) {
            // Use requestAnimationFrame instead of setInterval if available
            if ( requestAnimationFrame ) {
                timerId = true;
                raf = function() {
                    // When timerId gets set to null at any point, this stops
                    if ( timerId ) {
                        requestAnimationFrame( raf );
                        fx.tick();
                    }
                };
                requestAnimationFrame( raf );
            } else {
                timerId = setInterval( fx.tick, fx.interval );
            }
        }
    },
    

      http://stackoverflow.com/questions/7999680/why-doesnt-jquery-use-requestanimationframe

    为啥jquery 放弃,上面说的比较完善;

    animate源码如下

    ;(function() {
    
      var lastTime = 0;
      var vendors = ['ms', 'moz', 'webkit', 'o'];
    
      for(var x = 0; x < vendors.length && !window.requestAnimationFrame; ++x) {
        window.requestAnimationFrame = window[vendors[x]+'RequestAnimationFrame'];
        window.cancelAnimationFrame = window[vendors[x]+'CancelAnimationFrame'] || window[vendors[x]+'CancelRequestAnimationFrame'];
      }
    
      if (!window.requestAnimationFrame) {
        window.requestAnimationFrame = function(callback, element) {
          var currTime = new Date().getTime();
          var timeToCall = Math.max(0, 16 - (currTime - lastTime));
          var id = window.setTimeout(function() { callback(currTime + timeToCall); },
            timeToCall);
          lastTime = currTime + timeToCall;
          return id;
        };
      }
    
      if (!window.cancelAnimationFrame) {
        window.cancelAnimationFrame = function(id) {
          clearTimeout(id);
        };
      }
    
    }());
    
    var getStyle=function (obj,attr){
        return obj.currentStyle ? obj.currentStyle[attr]:getComputedStyle(obj)[attr];
    }    
          
    var Tween = {
        linear: function (t, b, c, d){  //匀速
            return c*t/d + b;
        },
        easeIn: function(t, b, c, d){  //加速曲线
            return c*(t/=d)*t + b;
        },
        easeOut: function(t, b, c, d){  //减速曲线
            return -c *(t/=d)*(t-2) + b;
        },
        easeBoth: function(t, b, c, d){  //加速减速曲线
            if ((t/=d/2) < 1) {
                return c/2*t*t + b;
            }
            return -c/2 * ((--t)*(t-2) - 1) + b;
        },
        easeInStrong: function(t, b, c, d){  //加加速曲线
            return c*(t/=d)*t*t*t + b;
        },
        easeOutStrong: function(t, b, c, d){  //减减速曲线
            return -c * ((t=t/d-1)*t*t*t - 1) + b;
        },
        easeBothStrong: function(t, b, c, d){  //加加速减减速曲线
            if ((t/=d/2) < 1) {
                return c/2*t*t*t*t + b;
            }
            return -c/2 * ((t-=2)*t*t*t - 2) + b;
        },
        elasticIn: function(t, b, c, d, a, p){  //正弦衰减曲线(弹动渐入)
            if (t === 0) { 
                return b; 
            }
            if ( (t /= d) == 1 ) {
                return b+c; 
            }
            if (!p) {
                p=d*0.3; 
            }
            if (!a || a < Math.abs(c)) {
                a = c; 
                var s = p/4;
            } else {
                var s = p/(2*Math.PI) * Math.asin (c/a);
            }
            return -(a*Math.pow(2,10*(t-=1)) * Math.sin( (t*d-s)*(2*Math.PI)/p )) + b;
        },
        elasticOut: function(t, b, c, d, a, p){    //正弦增强曲线(弹动渐出)
            if (t === 0) {
                return b;
            }
            if ( (t /= d) == 1 ) {
                return b+c;
            }
            if (!p) {
                p=d*0.3;
            }
            if (!a || a < Math.abs(c)) {
                a = c;
                var s = p / 4;
            } else {
                var s = p/(2*Math.PI) * Math.asin (c/a);
            }
            return a*Math.pow(2,-10*t) * Math.sin( (t*d-s)*(2*Math.PI)/p ) + c + b;
        },    
        elasticBoth: function(t, b, c, d, a, p){
            if (t === 0) {
                return b;
            }
            if ( (t /= d/2) == 2 ) {
                return b+c;
            }
            if (!p) {
                p = d*(0.3*1.5);
            }
            if ( !a || a < Math.abs(c) ) {
                a = c; 
                var s = p/4;
            }
            else {
                var s = p/(2*Math.PI) * Math.asin (c/a);
            }
            if (t < 1) {
                return - 0.5*(a*Math.pow(2,10*(t-=1)) * 
                        Math.sin( (t*d-s)*(2*Math.PI)/p )) + b;
            }
            return a*Math.pow(2,-10*(t-=1)) * 
                    Math.sin( (t*d-s)*(2*Math.PI)/p )*0.5 + c + b;
        }
    }
    
    
    
    
    function animate(obj,json,times,fx,fn){
        
        if( typeof times == 'undefined' ){
            times = 400;
            fx = 'linear';
        }
        
        if( typeof times == 'string' ){
            if(typeof fx == 'function'){
                fn = fx;
            }
            fx = times;
            times = 400;
        }
        else if(typeof times == 'function'){
            fn = times;
            times = 400;
            fx = 'linear';
        }
        else if(typeof times == 'number'){
            if(typeof fx == 'function'){
                fn = fx;
                fx = 'linear';
            }
            else if(typeof fx == 'undefined'){
                fx = 'linear';
            }
        }
        
        
    
        var iCur = {};
        var startTime = +new Date();
        
        for(var attr in json){
            iCur[attr] = 0;
            
            if( attr == 'opacity' ){
                if(Math.round(getStyle(obj,attr)*100) == 0){
                    iCur[attr] = 0;
                }
                else{
                    iCur[attr] = Math.round(getStyle(obj,attr)*100) || 100;
                }
            }
            else if(attr == 'scrollTop' ){
                     iCur[attr]=window.scrollY||document.documentElement.scrollTop || window.pageYOffset || document.body.scrollTop;;         
                }
            else{
                iCur[attr] = parseInt(getStyle(obj,attr)) || 0;
            }
            
        }
        
        
            if(obj.timer){
            cancelAnimationFrame(obj.timer)
            }
            //obj.timer=null;
        
        function update(){    
            
            var changeTime = +new Date();
            var scale = 1 - Math.max(0,startTime - changeTime + times)/times;
            
            for(var attr in json){
                
                var value = Tween[fx](scale*times, iCur[attr] , json[attr] - iCur[attr] , times );
                
                if(attr == 'opacity'){
                    obj.style.filter = 'alpha(opacity='+ value +')';
                    obj.style.opacity = value/100;
                }else if(attr == 'scrollTop'){
                     window.scrollTo(0, value); 
               }else{
                    obj.style[attr] = value + 'px';
                }
                
            }
            
            if(scale == 1){
                    cancelAnimationFrame(obj.timer);
                     fn&&fn.apply(this, arguments);
            }else{
                 //setup_fps_meters();
                obj.timer=requestAnimationFrame(arguments.callee);
                }
            
       }//update  end
       //    requestAnimationFrame(update);  //某些时候 画的过快  有bug
        update();
        
    }    
        
        
    Tween.js  
    /*
    
    * t : time 已过时间
    * b : begin 起始值
    * c : count 总的运动值
    * d : duration 持续时间
    * */
     
    //Tween.linear();

    css cubic-bezier 缓动备份查看  注意点:x1,x2,y1,y2的值范围在[0, 1]。

    var easingMap = {
      "linear": [0.250, 0.250, 0.750, 0.750],
      "ease": [0.250, 0.100, 0.250, 1.000],
      "easeIn": [0.420, 0.000, 1.000, 1.000],
      "easeOut": [0.000, 0.000, 0.580, 1.000],
      "easeInOut": [0.420, 0.000, 0.580, 1.000],
      "easeInQuad": [0.550, 0.085, 0.680, 0.530],
      "easeInCubic": [0.550, 0.055, 0.675, 0.190],
      "easeInQuart": [0.895, 0.030, 0.685, 0.220],
      "easeInQuint": [0.755, 0.050, 0.855, 0.060],
      "easeInSine": [0.470, 0.000, 0.745, 0.715],
      "easeInExpo": [0.950, 0.050, 0.795, 0.035],
      "easeInCirc": [0.600, 0.040, 0.980, 0.335],
      "easeInBack": [0.600, -0.280, 0.735, 0.045],
      "easeOutQuad": [0.250, 0.460, 0.450, 0.940],
      "easeOutCubic": [0.215, 0.610, 0.355, 1.000],
      "easeOutQuart": [0.165, 0.840, 0.440, 1.000],
      "easeOutQuint": [0.230, 1.000, 0.320, 1.000],
      "easeOutSine": [0.390, 0.575, 0.565, 1.000],
      "easeOutExpo": [0.190, 1.000, 0.220, 1.000],
      "easeOutCirc": [0.075, 0.820, 0.165, 1.000],
      "easeOutBack": [0.175, 0.885, 0.320, 1.275],
      "easeInOutQuad": [0.455, 0.030, 0.515, 0.955],
      "easeInOutCubic": [0.645, 0.045, 0.355, 1.000],
      "easeInOutQuart": [0.770, 0.000, 0.175, 1.000],
      "easeInOutQuint": [0.860, 0.000, 0.070, 1.000],
      "easeInOutSine": [0.445, 0.050, 0.550, 0.950],
      "easeInOutExpo": [1.000, 0.000, 0.000, 1.000],
      "easeInOutCirc": [0.785, 0.135, 0.150, 0.860],
      "easeInOutBack": [0.680, -0.550, 0.265, 1.550],
      "custom": [0.000, 0.350, 0.500, 1.300],
      "random": [Math.random().toFixed(3),
          Math.random().toFixed(3),
          Math.random().toFixed(3),
          Math.random().toFixed(3)]
        }

    This curve contains values out of range. But fear not young padawan! Just use cubic-bezier(.25,.1,.39,1) as well for Webkit until the bug #45761 fix propagates to Safari.

     接近ios 原生 的切换 cubic-bezier(0.42, 0, 0.58, 1.0)

    http://www.cnblogs.com/surfaces/

     

     // transform兼容
        function preTransform() {
            var cssPrefix,
            vendors = {
              '': '',
              Webkit: 'webkit',
              Moz: '',
              O: 'o',
              ms: 'ms'
            },
            testEle = document.createElement('p'),
            cssSupport = {};
     
             // 嗅探特性
            Object.keys(vendors).some(function(vendor) {
                if (testEle.style[vendor + (vendor ? 'T' : 't') + 'ransform'] !== undefined) {
                  cssPrefix = vendor ? '-' + vendor.toLowerCase() + '-' : '';
                  return true;
                }
            });
     
          function normalizeCss(name) {
            name = name.toLowerCase();
            return cssPrefix ? cssPrefix + name : name;
          }
     
          cssSupport = {
            transform: normalizeCss('Transform'),
          }
     
          return cssSupport.transform;
        }
    }());
    

      

     参考资料:

    snabbt.js

     http://daniel-lundin.github.io/snabbt.js/index.html

    jquery.transit.js

    Zepto.js

    Bootstrap.transition.js jquery.js

     

    
    
  • 相关阅读:
    十步完全理解SQL
    c#退出应用程序办法
    几个有意思的算法题
    GeoServer不同服务器安装配置、数据发布及客户端访问
    开启httpd服务的时候 显示Could not reliably determine the server`s fully qualified domain name
    Working With OpenLayers(Section 1: Creating a Basic Map)
    GeoServer地图开发解决方案(五):基于Silverlight技术的地图客户端实现
    模拟远程HTTP的POST请求
    模拟提交带附件的表单
    支付宝手机网站接口对接
  • 原文地址:https://www.cnblogs.com/surfaces/p/5129868.html
Copyright © 2020-2023  润新知