javascript的缓动效果(第2部分)


这部分对原先的缓动函数进行抽象化,并结合缓动公式进行强化。成品的效果非常惊人逆天。走过路过不要错过。

  好了,打诨到此为止。普通的加速减速是难以让人满意的,为了实现弹簧等让人眼花缭乱的效果必须动用缓动公式。我见过两套缓动公式,一套是早期Robert Penner大神的缓动公式,内置到tween类中,不过现在人们越来越推荐tweenlite这个新秀了。另一套是script.aculo.us与mootools里面的,由于mootools可称之为prototype的升级版,script.aculo.us则是基于prototype,我们就把它们并称为prototype流派。与flash流派最大的不同是,它们封装得更好,并只需传入一个参数(0~1的小数),并且拥有严密的队列机制来调用各种回调函数。如在回调函数设置元素的长宽,就弄成Scale特效,利用它我们进一步制作SlideUp,SlideDown,Squish等复合特效。

  我们先来看flash流派的缓动公式,它们基本都有如下四个参数。

  t:timestamp,指缓动效果开始执行到当前帧开始执行时经过的时间段,单位ms

  b:beginning position,起始位置

  c:change,要移动的距离,就是终点位置减去起始位置。

  d: duration ,缓和效果持续的时间。

  我们把这四个参数传入Robert Penner大神的缓动公式,它就会计算出当前帧物体移动的位置。我们对比原来的函数来改写。

 var transition = function(el){ 
  transition.linear = function(t,b,c,d){ return c*t/d + b; };//免费提供一个缓动公式(匀速运动公式) 
  el.style.position = "absolute"; 
  var options = arguments[1] || {}, 
  begin = getCoords(el).left,//开始位置 
  change = parseFloat(getStyle(_("taxiway"),"width")) - parseFloat(getStyle(el,"width")),//要移动的距离 
  duration = options.duration || 500,//缓动效果持续时间 
  ease = options.ease || transition.linear,//要使用的缓动公式 
  end = begin + change,//结束位置 
  startTime = new Date().getTime();//开始执行的时间 
  (function(){ 
   setTimeout(function(){ 
    var newTime = new Date().getTime(),//当前帧开始的时间 
    timestamp = newTime - startTime;//逝去时间 
    el.style.left = ease(timestamp,begin,change,duration) + "px";//移动 
    if(duration <= timestamp){ 
     el.style.left = end + "px"; 
    }else{ 
     setTimeout(arguments.callee,25);//每移动一次停留25毫秒 
    } 
   },25) 
  })() 
 } 

  接着是各种缓动公式大阅兵,共分为十一大类,除了linear。其他类又分为三种。

  easeIn方法控制补间如何从开始到最高速度。

  easeOut 方法控制补间减速并停在目标位置

  easeInOut方法同时控制上述两者。

  具体公式见下面(共31种)。

//***********@author:Robert Penner and cloudgamer************* 
//http://www.cnblogs.com/cloudgamer/archive/2009/01/06/Tween.html 
 var Tween = { 
  Linear: function(t,b,c,d){ return c*t/d + b; }, 
  Quad: { 
   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; 
   }, 
   easeInOut: function(t,b,c,d){ 
    if ((t/=d/2) < 1) return c/2*t*t + b; 
    return -c/2 * ((--t)*(t-2) - 1) + b; 
   } 
  }, 
  Cubic: { 
   easeIn: function(t,b,c,d){ 
    return c*(t/=d)*t*t + b; 
   }, 
   easeOut: function(t,b,c,d){ 
    return c*((t=t/d-1)*t*t + 1) + b; 
   }, 
   easeInOut: function(t,b,c,d){ 
    if ((t/=d/2) < 1) return c/2*t*t*t + b; 
    return c/2*((t-=2)*t*t + 2) + b; 
   } 
  }, 
  Quart: { 
   easeIn: function(t,b,c,d){ 
    return c*(t/=d)*t*t*t + b; 
   }, 
   easeOut: function(t,b,c,d){ 
    return -c * ((t=t/d-1)*t*t*t - 1) + b; 
   }, 
   easeInOut: 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; 
   } 
  }, 
  Quint: { 
   easeIn: function(t,b,c,d){ 
    return c*(t/=d)*t*t*t*t + b; 
   }, 
   easeOut: function(t,b,c,d){ 
    return c*((t=t/d-1)*t*t*t*t + 1) + b; 
   }, 
   easeInOut: function(t,b,c,d){ 
    if ((t/=d/2) < 1) return c/2*t*t*t*t*t + b; 
    return c/2*((t-=2)*t*t*t*t + 2) + b; 
   } 
  }, 
  Sine: { 
   easeIn: function(t,b,c,d){ 
    return -c * Math.cos(t/d * (Math.PI/2)) + c + b; 
   }, 
   easeOut: function(t,b,c,d){ 
    return c * Math.sin(t/d * (Math.PI/2)) + b; 
   }, 
   easeInOut: function(t,b,c,d){ 
    return -c/2 * (Math.cos(Math.PI*t/d) - 1) + b; 
   } 
  }, 
  Expo: { 
   easeIn: function(t,b,c,d){ 
    return (t==0) ? b : c * Math.pow(2, 10 * (t/d - 1)) + b; 
   }, 
   easeOut: function(t,b,c,d){ 
    return (t==d) ? b+c : c * (-Math.pow(2, -10 * t/d) + 1) + b; 
   }, 
   easeInOut: function(t,b,c,d){ 
    if (t==0) return b; 
    if (t==d) return b+c; 
    if ((t/=d/2) < 1) return c/2 * Math.pow(2, 10 * (t - 1)) + b; 
    return c/2 * (-Math.pow(2, -10 * --t) + 2) + b; 
   } 
  }, 
  Circ: { 
   easeIn: function(t,b,c,d){ 
    return -c * (Math.sqrt(1 - (t/=d)*t) - 1) + b; 
   }, 
   easeOut: function(t,b,c,d){ 
    return c * Math.sqrt(1 - (t=t/d-1)*t) + b; 
   }, 
   easeInOut: function(t,b,c,d){ 
    if ((t/=d/2) < 1) return -c/2 * (Math.sqrt(1 - t*t) - 1) + b; 
    return c/2 * (Math.sqrt(1 - (t-=2)*t) + 1) + b; 
   } 
  }, 
  Elastic: { 
   easeIn: function(t,b,c,d,a,p){ 
    if (t==0) return b; if ((t/=d)==1) return b+c; if (!p) p=d*.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; 
   }, 
   easeOut: function(t,b,c,d,a,p){ 
    if (t==0) return b; if ((t/=d)==1) return b+c; if (!p) p=d*.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); 
   }, 
   easeInOut: function(t,b,c,d,a,p){ 
    if (t==0) return b; if ((t/=d/2)==2) return b+c; if (!p) p=d*(.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 -.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 )*.5 + c + b; 
   } 
  }, 
  Back: { 
   easeIn: function(t,b,c,d,s){ 
    if (s == undefined) s = 1.70158; 
    return c*(t/=d)*t*((s+1)*t - s) + b; 
   }, 
   easeOut: function(t,b,c,d,s){ 
    if (s == undefined) s = 1.70158; 
    return c*((t=t/d-1)*t*((s+1)*t + s) + 1) + b; 
   }, 
   easeInOut: function(t,b,c,d,s){ 
    if (s == undefined) s = 1.70158; 
    if ((t/=d/2) < 1) return c/2*(t*t*(((s*=(1.525))+1)*t - s)) + b; 
    return c/2*((t-=2)*t*(((s*=(1.525))+1)*t + s) + 2) + b; 
   } 
  }, 
  Bounce: { 
   easeIn: function(t,b,c,d){ 
    return c - Tween.Bounce.easeOut(d-t, 0, c, d) + b; 
   }, 
   easeOut: function(t,b,c,d){ 
    if ((t/=d) < (1/2.75)) { 
     return c*(7.5625*t*t) + b; 
    } else if (t < (2/2.75)) { 
     return c*(7.5625*(t-=(1.5/2.75))*t + .75) + b; 
    } else if (t < (2.5/2.75)) { 
     return c*(7.5625*(t-=(2.25/2.75))*t + .9375) + b; 
    } else { 
     return c*(7.5625*(t-=(2.625/2.75))*t + .984375) + b; 
    } 
   }, 
   easeInOut: function(t,b,c,d){ 
    if (t < d/2) return Tween.Bounce.easeIn(t*2, 0, c, d) * .5 + b; 
    else return Tween.Bounce.easeOut(t*2-d, 0, c, d) * .5 + c*.5 + b; 
   } 
  } 
 } 

<div id="taxiway"> 
 <div id="move" onclick="transition(this,{ease:Tween.Bounce.easeOut})"></div> 
</div> 

  但我不喜欢flash流派的缓动公式,为了使用prototype流派的缓动公式,我进一步改进与抽象化我的缓动函数

//******************@author : 司徒正美************ 
 var transition = function(el){ 
  el.style.position = "absolute"; 
  var options = arguments[1] || {}, 
  begin = options.begin,//开始位置 
  change = options.change,//变化量 
  duration = options.duration || 500,//缓动效果持续时间 
  field = options.field,//必须指定,基本上对top,left,width,height这个属性进行设置 
  ftp = options.ftp || 50, 
  onStart = options.onStart || function(){}, 
  onEnd = options.onEnd || function(){}, 
  ease = options.ease,//要使用的缓动公式 
  end = begin + change,//结束位置 
  startTime = new Date().getTime();//开始执行的时间 
  onStart(); 
  (function(){ 
   setTimeout(function(){ 
    var newTime = new Date().getTime(),//当前帧开始的时间 
    timestamp = newTime - startTime,//逝去时间 
    delta = ease(timestamp / duration); 
    el.style[field] = Math.ceil(begin + delta * change) + "px" 
    if(duration <= timestamp){ 
     el.style[field] = end + "px"; 
     onEnd(); 
    }else{ 
     setTimeout(arguments.callee,1000/ftp); 
    } 
   },1000/ftp) 
  })() 
 } 
参数 类型  说明 
el element 必需,为页面元素
begin number 必需,开始的位置
change number 必需,要移动的距离
duration number 可选,缓动效果持续时间,默认是500ms。建议取300~1000ms。
field string 必需,要发生变化的样式属性。请在top,left,bottom,right,width与height中选择。
ftp number 可选,每秒进行多少帧动画,默认50帧,保证流畅播放。一些参考资料,日本动画1秒36帧,中国卡通24帧,赛车游戏60帧。
ease function 必需,缓动公式,参数为0~1之间的数。可参考我下面给出的45条公式。
onStart function 可选,在开始时执行。
onEnd function 可选,在结束时执行。


  prototype流派的缓动公式,只需一个参数(增至45种)

var tween = { 
  easeInQuad: function(pos){ 
   return Math.pow(pos, 2); 
  }, 
 
  easeOutQuad: function(pos){ 
   return -(Math.pow((pos-1), 2) -1); 
  }, 
 
  easeInOutQuad: function(pos){ 
   if ((pos/=0.5) < 1) return 0.5*Math.pow(pos,2); 
   return -0.5 * ((pos-=2)*pos - 2); 
  }, 
 
  easeInCubic: function(pos){ 
   return Math.pow(pos, 3); 
  }, 
 
  easeOutCubic: function(pos){ 
   return (Math.pow((pos-1), 3) +1); 
  }, 
 
  easeInOutCubic: function(pos){ 
   if ((pos/=0.5) < 1) return 0.5*Math.pow(pos,3); 
   return 0.5 * (Math.pow((pos-2),3) + 2); 
  }, 
 
  easeInQuart: function(pos){ 
   return Math.pow(pos, 4); 
  }, 
 
  easeOutQuart: function(pos){ 
   return -(Math.pow((pos-1), 4) -1) 
  }, 
 
  easeInOutQuart: function(pos){ 
   if ((pos/=0.5) < 1) return 0.5*Math.pow(pos,4); 
   return -0.5 * ((pos-=2)*Math.pow(pos,3) - 2); 
  }, 
 
  easeInQuint: function(pos){ 
   return Math.pow(pos, 5); 
  }, 
 
  easeOutQuint: function(pos){ 
   return (Math.pow((pos-1), 5) +1); 
  }, 
 
  easeInOutQuint: function(pos){ 
   if ((pos/=0.5) < 1) return 0.5*Math.pow(pos,5); 
   return 0.5 * (Math.pow((pos-2),5) + 2); 
  }, 
 
  easeInSine: function(pos){ 
   return -Math.cos(pos * (Math.PI/2)) + 1; 
  }, 
 
  easeOutSine: function(pos){ 
   return Math.sin(pos * (Math.PI/2)); 
  }, 
 
  easeInOutSine: function(pos){ 
   return (-.5 * (Math.cos(Math.PI*pos) -1)); 
  }, 
 
  easeInExpo: function(pos){ 
   return (pos==0) ? 0 : Math.pow(2, 10 * (pos - 1)); 
  }, 
 
  easeOutExpo: function(pos){ 
   return (pos==1) ? 1 : -Math.pow(2, -10 * pos) + 1; 
  }, 
 
  easeInOutExpo: function(pos){ 
   if(pos==0) return 0; 
   if(pos==1) return 1; 
   if((pos/=0.5) < 1) return 0.5 * Math.pow(2,10 * (pos-1)); 
   return 0.5 * (-Math.pow(2, -10 * --pos) + 2); 
  }, 
 
  easeInCirc: function(pos){ 
   return -(Math.sqrt(1 - (pos*pos)) - 1); 
  }, 
 
  easeOutCirc: function(pos){ 
   return Math.sqrt(1 - Math.pow((pos-1), 2)) 
  }, 
 
  easeInOutCirc: function(pos){ 
   if((pos/=0.5) < 1) return -0.5 * (Math.sqrt(1 - pos*pos) - 1); 
   return 0.5 * (Math.sqrt(1 - (pos-=2)*pos) + 1); 
  }, 
 
  easeOutBounce: function(pos){ 
   if ((pos) < (1/2.75)) { 
    return (7.5625*pos*pos); 
   } else if (pos < (2/2.75)) { 
    return (7.5625*(pos-=(1.5/2.75))*pos + .75); 
   } else if (pos < (2.5/2.75)) { 
    return (7.5625*(pos-=(2.25/2.75))*pos + .9375); 
   } else { 
    return (7.5625*(pos-=(2.625/2.75))*pos + .984375); 
   } 
  }, 
 
  easeInBack: function(pos){ 
   var s = 1.70158; 
   return (pos)*pos*((s+1)*pos - s); 
  }, 
 
  easeOutBack: function(pos){ 
   var s = 1.70158; 
   return (pos=pos-1)*pos*((s+1)*pos + s) + 1; 
  }, 
 
  easeInOutBack: function(pos){ 
   var s = 1.70158; 
   if((pos/=0.5) < 1) return 0.5*(pos*pos*(((s*=(1.525))+1)*pos -s)); 
   return 0.5*((pos-=2)*pos*(((s*=(1.525))+1)*pos +s) +2); 
  }, 
 
  elastic: function(pos) { 
   return -1 * Math.pow(4,-8*pos) * Math.sin((pos*6-1)*(2*Math.PI)/2) + 1; 
  }, 
 
  swingFromTo: function(pos) { 
   var s = 1.70158; 
   return ((pos/=0.5) < 1) ? 0.5*(pos*pos*(((s*=(1.525))+1)*pos - s)) : 
    0.5*((pos-=2)*pos*(((s*=(1.525))+1)*pos + s) + 2); 
  }, 
 
  swingFrom: function(pos) { 
   var s = 1.70158; 
   return pos*pos*((s+1)*pos - s); 
  }, 
 
  swingTo: function(pos) { 
   var s = 1.70158; 
   return (pos-=1)*pos*((s+1)*pos + s) + 1; 
  }, 
 
  bounce: function(pos) { 
   if (pos < (1/2.75)) { 
    return (7.5625*pos*pos); 
   } else if (pos < (2/2.75)) { 
    return (7.5625*(pos-=(1.5/2.75))*pos + .75); 
   } else if (pos < (2.5/2.75)) { 
    return (7.5625*(pos-=(2.25/2.75))*pos + .9375); 
   } else { 
    return (7.5625*(pos-=(2.625/2.75))*pos + .984375); 
   } 
  }, 
 
  bouncePast: function(pos) { 
   if (pos < (1/2.75)) { 
    return (7.5625*pos*pos); 
   } else if (pos < (2/2.75)) { 
    return 2 - (7.5625*(pos-=(1.5/2.75))*pos + .75); 
   } else if (pos < (2.5/2.75)) { 
    return 2 - (7.5625*(pos-=(2.25/2.75))*pos + .9375); 
   } else { 
    return 2 - (7.5625*(pos-=(2.625/2.75))*pos + .984375); 
   } 
  }, 
 
  easeFromTo: function(pos) { 
   if ((pos/=0.5) < 1) return 0.5*Math.pow(pos,4); 
   return -0.5 * ((pos-=2)*Math.pow(pos,3) - 2); 
  }, 
 
  easeFrom: function(pos) { 
   return Math.pow(pos,4); 
  }, 
 
  easeTo: function(pos) { 
   return Math.pow(pos,0.25); 
  }, 
 
  linear: function(pos) { 
   return pos 
  }, 
 
  sinusoidal: function(pos) { 
   return (-Math.cos(pos*Math.PI)/2) + 0.5; 
  }, 
 
  reverse: function(pos) { 
   return 1 - pos; 
  }, 
 
  mirror: function(pos, transition) { 
   transition = transition || tween.sinusoidal; 
   if(pos<0.5) 
    return transition(pos*2); 
   else 
    return transition(1-(pos-0.5)*2); 
  }, 
 
  flicker: function(pos) { 
   var pos = pos + (Math.random()-0.5)/5; 
   return tween.sinusoidal(pos < 0 ? 0 : pos > 1 ? 1 : pos); 
  }, 
 
  wobble: function(pos) { 
   return (-Math.cos(pos*Math.PI*(9*pos))/2) + 0.5; 
  }, 
 
  pulse: function(pos, pulses) { 
   return (-Math.cos((pos*((pulses||5)-.5)*2)*Math.PI)/2) + .5; 
  }, 
 
  blink: function(pos, blinks) { 
   return Math.round(pos*(blinks||5)) % 2; 
  }, 
 
  spring: function(pos) { 
   return 1 - (Math.cos(pos * 4.5 * Math.PI) * Math.exp(-pos * 6)); 
  }, 
 
  none: function(pos){ 
   return 0 
  }, 
 
  full: function(pos){ 
   return 1 
  } 
 }

 
<!doctype html>
<html dir="ltr" lang="zh-CN">
    <head>
        <meta charset="utf-8"/>
        <meta http-equiv="X-UA-Compatible" content="IE=8">
        <style type="text/css">
            .taxiway{
                width:800px;
                height:100px;
                background:#E8E8FF;
            }
            .move{
                width:100px;
                height:100px;
                background:#a9ea00;
            }
            #panel {
                float:left;
                width:810px
            }
            #panel div{
                float:left;
                width:88px;
                border:1px solid #333;
                height:20px;
                font-size:11px;
            }
            div.transition {
                margin-top: 30px;
                width: 200px;
                height: 200px;
                position: relative;
                margin-bottom:10px;
            }

            div.transition div {
                position: absolute;
                height: 1px;
                width: 1px;
                background: #000;
            }

            div.transition span {
                display: block;
                position: absolute;
                border-bottom: 1px solid #dadada;
                font-size: 10px;
                color: #888;
                width: 200px;
                left: 0px;
            }
            div.transition div#indicator {
                position:absolute;
                background-color:#a9ea00;
                height: 200px;
                top: 0px;
                left: 0px;
            }

            div.transition div#marker {
                background-color: #f00;
                height: 6px;
                width: 6px;
                border-radius: 3px;
                -webkit-border-radius: 3px;
                -moz-border-radius: 3px;
                left: 0px;
                margin-bottom: -3px;
                margin-left: -3px;
            }
            div.transition div#label {
                background: transparent;
                color: #ABD474;
                font-size: 20px;
                height: 20px;
                width: 200px;
                text-align: center;
                top: 80px;
                left: 0px;
                z-index: -1;
            }

        </style>
        <script type="text/javascript">
            var getCoords = function(el){
                var box = el.getBoundingClientRect(),
                doc = el.ownerDocument,
                body = doc.body,
                html = doc.documentElement,
                clientTop = html.clientTop || body.clientTop || 0,
                clientLeft = html.clientLeft || body.clientLeft || 0,
                top  = box.top  + (self.pageYOffset || html.scrollTop  ||  body.scrollTop ) - clientTop,
                left = box.left + (self.pageXOffset || html.scrollLeft ||  body.scrollLeft) - clientLeft
                return { 'top': top, 'left': left };
            };

            var getStyle = function(el, style){
                if(!+"\v1"){
                    style = style.replace(/\-(\w)/g, function(all, letter){
                        return letter.toUpperCase();
                    });
                    var value = el.currentStyle[style];
                    (value == "auto")&&(value = "0px" );
                    return value;
                }else{
                    return document.defaultView.getComputedStyle(el, null).getPropertyValue(style)
                }
            }
            var tween = {
                easeInQuad: function(pos){
                    return Math.pow(pos, 2);
                },

                easeOutQuad: function(pos){
                    return -(Math.pow((pos-1), 2) -1);
                },

                easeInOutQuad: function(pos){
                    if ((pos/=0.5) < 1) return 0.5*Math.pow(pos,2);
                    return -0.5 * ((pos-=2)*pos - 2);
                },

                easeInCubic: function(pos){
                    return Math.pow(pos, 3);
                },

                easeOutCubic: function(pos){
                    return (Math.pow((pos-1), 3) +1);
                },

                easeInOutCubic: function(pos){
                    if ((pos/=0.5) < 1) return 0.5*Math.pow(pos,3);
                    return 0.5 * (Math.pow((pos-2),3) + 2);
                },

                easeInQuart: function(pos){
                    return Math.pow(pos, 4);
                },

                easeOutQuart: function(pos){
                    return -(Math.pow((pos-1), 4) -1)
                },

                easeInOutQuart: function(pos){
                    if ((pos/=0.5) < 1) return 0.5*Math.pow(pos,4);
                    return -0.5 * ((pos-=2)*Math.pow(pos,3) - 2);
                },

                easeInQuint: function(pos){
                    return Math.pow(pos, 5);
                },

                easeOutQuint: function(pos){
                    return (Math.pow((pos-1), 5) +1);
                },

                easeInOutQuint: function(pos){
                    if ((pos/=0.5) < 1) return 0.5*Math.pow(pos,5);
                    return 0.5 * (Math.pow((pos-2),5) + 2);
                },

                easeInSine: function(pos){
                    return -Math.cos(pos * (Math.PI/2)) + 1;
                },

                easeOutSine: function(pos){
                    return Math.sin(pos * (Math.PI/2));
                },

                easeInOutSine: function(pos){
                    return (-.5 * (Math.cos(Math.PI*pos) -1));
                },

                easeInExpo: function(pos){
                    return (pos==0) ? 0 : Math.pow(2, 10 * (pos - 1));
                },

                easeOutExpo: function(pos){
                    return (pos==1) ? 1 : -Math.pow(2, -10 * pos) + 1;
                },

                easeInOutExpo: function(pos){
                    if(pos==0) return 0;
                    if(pos==1) return 1;
                    if((pos/=0.5) < 1) return 0.5 * Math.pow(2,10 * (pos-1));
                    return 0.5 * (-Math.pow(2, -10 * --pos) + 2);
                },

                easeInCirc: function(pos){
                    return -(Math.sqrt(1 - (pos*pos)) - 1);
                },

                easeOutCirc: function(pos){
                    return Math.sqrt(1 - Math.pow((pos-1), 2))
                },

                easeInOutCirc: function(pos){
                    if((pos/=0.5) < 1) return -0.5 * (Math.sqrt(1 - pos*pos) - 1);
                    return 0.5 * (Math.sqrt(1 - (pos-=2)*pos) + 1);
                },

                easeOutBounce: function(pos){
                    if ((pos) < (1/2.75)) {
                        return (7.5625*pos*pos);
                    } else if (pos < (2/2.75)) {
                        return (7.5625*(pos-=(1.5/2.75))*pos + .75);
                    } else if (pos < (2.5/2.75)) {
                        return (7.5625*(pos-=(2.25/2.75))*pos + .9375);
                    } else {
                        return (7.5625*(pos-=(2.625/2.75))*pos + .984375);
                    }
                },

                easeInBack: function(pos){
                    var s = 1.70158;
                    return (pos)*pos*((s+1)*pos - s);
                },

                easeOutBack: function(pos){
                    var s = 1.70158;
                    return (pos=pos-1)*pos*((s+1)*pos + s) + 1;
                },

                easeInOutBack: function(pos){
                    var s = 1.70158;
                    if((pos/=0.5) < 1) return 0.5*(pos*pos*(((s*=(1.525))+1)*pos -s));
                    return 0.5*((pos-=2)*pos*(((s*=(1.525))+1)*pos +s) +2);
                },

                elastic: function(pos) {
                    return -1 * Math.pow(4,-8*pos) * Math.sin((pos*6-1)*(2*Math.PI)/2) + 1;
                },

                swingFromTo: function(pos) {
                    var s = 1.70158;
                    return ((pos/=0.5) < 1) ? 0.5*(pos*pos*(((s*=(1.525))+1)*pos - s)) :
                        0.5*((pos-=2)*pos*(((s*=(1.525))+1)*pos + s) + 2);
                },

                swingFrom: function(pos) {
                    var s = 1.70158;
                    return pos*pos*((s+1)*pos - s);
                },

                swingTo: function(pos) {
                    var s = 1.70158;
                    return (pos-=1)*pos*((s+1)*pos + s) + 1;
                },

                bounce: function(pos) {
                    if (pos < (1/2.75)) {
                        return (7.5625*pos*pos);
                    } else if (pos < (2/2.75)) {
                        return (7.5625*(pos-=(1.5/2.75))*pos + .75);
                    } else if (pos < (2.5/2.75)) {
                        return (7.5625*(pos-=(2.25/2.75))*pos + .9375);
                    } else {
                        return (7.5625*(pos-=(2.625/2.75))*pos + .984375);
                    }
                },

                bouncePast: function(pos) {
                    if (pos < (1/2.75)) {
                        return (7.5625*pos*pos);
                    } else if (pos < (2/2.75)) {
                        return 2 - (7.5625*(pos-=(1.5/2.75))*pos + .75);
                    } else if (pos < (2.5/2.75)) {
                        return 2 - (7.5625*(pos-=(2.25/2.75))*pos + .9375);
                    } else {
                        return 2 - (7.5625*(pos-=(2.625/2.75))*pos + .984375);
                    }
                },

                easeFromTo: function(pos) {
                    if ((pos/=0.5) < 1) return 0.5*Math.pow(pos,4);
                    return -0.5 * ((pos-=2)*Math.pow(pos,3) - 2);
                },

                easeFrom: function(pos) {
                    return Math.pow(pos,4);
                },

                easeTo: function(pos) {
                    return Math.pow(pos,0.25);
                },

                linear:  function(pos) {
                    return pos
                },

                sinusoidal: function(pos) {
                    return (-Math.cos(pos*Math.PI)/2) + 0.5;
                },

                reverse: function(pos) {
                    return 1 - pos;
                },

                mirror: function(pos, transition) {
                    transition = transition || tween.sinusoidal;
                    if(pos<0.5)
                        return transition(pos*2);
                    else
                        return transition(1-(pos-0.5)*2);
                },

                flicker: function(pos) {
                    var pos = pos + (Math.random()-0.5)/5;
                    return tween.sinusoidal(pos < 0 ? 0 : pos > 1 ? 1 : pos);
                },

                wobble: function(pos) {
                    return (-Math.cos(pos*Math.PI*(9*pos))/2) + 0.5;
                },

                pulse: function(pos, pulses) {
                    return (-Math.cos((pos*((pulses||5)-.5)*2)*Math.PI)/2) + .5;
                },

                blink: function(pos, blinks) {
                    return Math.round(pos*(blinks||5)) % 2;
                },

                spring: function(pos) {
                    return 1 - (Math.cos(pos * 4.5 * Math.PI) * Math.exp(-pos * 6));
                },

                none: function(pos){
                    return 0
                },

                full: function(pos){
                    return 1
                }
            }

            var _ = function(id){
                return document.getElementById(id);
            }
            var transition = function(el){
                el.style.position = "absolute";
                var options = arguments[1] || {},
                begin =  options.begin,//开始位置
                change = options.change,//变化量
                duration = options.duration || 500,//缓动效果持续时间
                field = options.field,//必须指定,基本上对top,left,width,height这个属性进行设置
                ftp = options.ftp || 50,
                onEnd = options.onEnd || function(){},
                ease = options.ease,//要使用的缓动公式
                end = begin + change,//结束位置
                startTime = new Date().getTime();//开始执行的时间
                (function(){
                    setTimeout(function(){
                        var newTime = new Date().getTime(),//当前帧开始的时间
                        timestamp = newTime - startTime,//逝去时间
                        delta = ease(timestamp / duration);
                        el.style[field] = Math.ceil(begin + delta * change) + "px"
                        if(duration <= timestamp){
                            el.style[field] = end + "px";
                            onEnd();
                        }else{
                            setTimeout(arguments.callee,1000/ftp);
                        }
                    },1000/ftp)
                })()
            }

            if (typeof Array.prototype['max'] == 'undefined') {
                Array.prototype.map = function(fn, thisObj) {
                    var scope = thisObj || window;
                    var a = [];
                    for ( var i=0, j=this.length; i < j; ++i ) {
                        a.push(fn.call(scope, this[i], i, this));
                    }
                    return a;
                };
                Array.prototype.max = function(){
                    return Math.max.apply({},this)
                }
                Array.prototype.min = function(){
                    return Math.min.apply({},this)
                }
            }

            var range = function(start,end){
                var _range = []
                for(var i = start,l=end-start;i<l;i++){
                    _range.push(i)
                }
                return _range
            }

            var draw = function(ease){
                var demo = _("transition");
                demo.innerHTML = "";//还原!
                //***********绘制控制台********************
                var values = range(0,200).map(function(v){
                    return  tween[ease](v/200) * 200;
                }),
                max = Math.max(200, values.max()),
                min = Math.min(0, values.min());
                if (min==max) {
                    min = 0;
                    max = 200;
                }
                var factor = 200/(max-min),
                grid = '<span style="bottom:'+Math.round((0-min)*factor)+'px">0</span>'+
                    '<span style="bottom:'+Math.round((200-min)*factor)+'px">1</span>',
                graph = range(0,200).map(function(v){
                    return '<div style="left:'+v+'px;bottom:'+Math.round((values[v]-min)*factor)+'px;height:1px"></div>';
                }).join('') + '<div id="indicator" style="display:none">'
                    +'</div><div id="marker" style="display:none"></div><div id="label"></div>';
                demo.innerHTML = grid + graph;
                var indicator = _("indicator"),
                marker = _("marker"),
                label = _("label"),
                demoTransition = function(pos){
                    var value = tween[ease](pos);
                    indicator.style.display = "block";
                    marker.style.display = "block";
                    marker.style.left = Math.round(pos*200)+'px';
                    marker.style.bottom = Math.round((value*200-min)*factor)+'px';
                    label.innerHTML = Math.round(pos*200)+'px';
                    return value;
                }
                transition(i


« 
» 
快速导航

Copyright © 2016 phpStudy | 豫ICP备2021030365号-3