基于時間的動畫函數(shù)

基于時間的動畫函數(shù)是適用于大多數(shù)情況,避免了由于頁面切換造成的動畫不連貫現(xiàn)象,同時jquery內(nèi)部也使用的這種方法。下面是源碼,結(jié)合源碼看一下就明白了。

<script>
   var btn=document.getElementsByClassName("button-success")[0];
   var dv=document.getElementsByClassName("div")[0];
   btn.onclick= function () {
      getStyle(dv,"left");
      move(dv,2000,{
         left:"200",
         top:"300",
      },"elasticBoth", function () {
         console.log(1);
      })
   }
   var move= function (obj,t, JSON, type, fn) {
      var startValue={};//獲取其實(shí)值
      var startTime=(new Date()).getTime();//獲取起始時間
      for(var attr in JSON){
         startValue[attr]=0;//初始化一個style對象
         if(attr ==="opacity"){
            startValue[attr]=Math.round(getStyle(obj,attr)*100);//兼容IE style是opacity的情況
         }else{
            startValue[attr]=parseInt(getStyle(obj,attr))
         }
      }
      clearInterval(obj.time);//避免多次觸發(fā)造成動畫疊加
      obj.time=setInterval(function () {
         var nowTime=(new Date()).getTime();//獲取現(xiàn)在時間
         var scale=1-Math.max(0,startTime+t-nowTime)/t;//通過tartTime+t-nowTime獲取隨著時間變化的變化率
         for(var attr in JSON){//對json形式的style進(jìn)行挨個賦值
            var value=Tween[type](scale*t,startValue[attr],JSON[attr]-startValue[attr],t);//Tween用法,這里把時間t設(shè)置為變化量,這樣就可以得到Tween處理后的變化值。
            if(attr==="opacity"){
               obj.style.filter='alpha(opacity'+value+')';
               obj.style.opacity=value/100;
            }else{
               obj.style[attr]=value+'px';
            }
         }
         if(scale===1){
            clearInterval(obj.time);
            if(fn){
               fn.call(obj);//觸發(fā)回調(diào)
            }
         }
      },30);

   }
   var getStyle= function (obj, attr) {
      if(obj.currentStyle){
         return obj.currentStyle[attr];
      }else{
         return getComputedStyle(obj,false)[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){    //正弦增強(qiáng)曲線(彈動漸出)
         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;
      },
      backIn: function(t, b, c, d, s){     //回退加速(回退漸入)
         if (typeof s == 'undefined') {
            s = 1.70158;
         }
         return c*(t/=d)*t*((s+1)*t - s) + b;
      },
      backOut: function(t, b, c, d, s){
         if (typeof s == 'undefined') {
            s = 3.70158;  //回縮的距離
         }
         return c*((t=t/d-1)*t*((s+1)*t + s) + 1) + b;
      },
      backBoth: function(t, b, c, d, s){
         if (typeof 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;
      },
      bounceIn: function(t, b, c, d){    //彈球減振(彈球漸出)
         return c - Tween['bounceOut'](d-t, 0, c, d) + b;
      },
      bounceOut: 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 + 0.75) + b;
         } else if (t < (2.5/2.75)) {
            return c*(7.5625*(t-=(2.25/2.75))*t + 0.9375) + b;
         }
         return c*(7.5625*(t-=(2.625/2.75))*t + 0.984375) + b;
      },
      bounceBoth: function(t, b, c, d){
         if (t < d/2) {
            return Tween['bounceIn'](t*2, 0, c, d) * 0.5 + b;
         }
         return Tween['bounceOut'](t*2-d, 0, c, d) * 0.5 + c*0.5 + b;
      }
   }
</script>

Linear:無緩動效果(勻速運(yùn)動);
Quadratic:二次方的緩動;
Cubic:三次方的緩動
Quartic:四次方的緩動;
Quintic :五次方的緩動;
Sinusoidal:正弦曲線的緩動;
Exponential:指數(shù)曲線的緩動;
Circular:圓形曲線的緩動;
Elastic:指數(shù)衰減的正弦曲線緩動;
Back:超過范圍的三次方緩動);
Bounce:指數(shù)衰減的反彈緩動。
每個效果都分三個緩動方式(方法),分別是:
easeIn:從0開始加速的運(yùn)動;
easeOut:減速到0的運(yùn)動;
easeInOut:前半段從0開始加速,后半段減速到0的運(yùn)動。
函數(shù)的四個參數(shù)分別代表:
t--- current time(當(dāng)前時間);
b--- beginning value(初始值);
c--- change in value(變化量);
d---duration(持續(xù)時間)
運(yùn)算的結(jié)果就是當(dāng)前的運(yùn)動路程。可以看到,只有t-current-time是能變化的,這樣就支持了根據(jù)時間來實(shí)現(xiàn)動畫。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

推薦閱讀更多精彩內(nèi)容

  • 鏈接 歡迎大家訪問我的個人網(wǎng)站四度空間 Fuse? 很多時候,設(shè)計師設(shè)計一個特效動畫出來,用靜態(tài)的UE是很難向開發(fā)...
    Carden閱讀 5,929評論 0 1
  • 1 背景 不能只分析源碼呀,分析的同時也要整理歸納基礎(chǔ)知識,剛好有人微博私信讓全面說說Android的動畫,所以今...
    未聞椛洺閱讀 2,750評論 0 10
  • 主要參考的文章 Zookeeper作用和典型應(yīng)用場景 Zookeeper作為一個分布式系統(tǒng),主要用來解決分布式集群...
    walker_liu_fei閱讀 377評論 0 0
  • 登山尋隱訪古風(fēng), 高岳峰回漫天紅。 望夫石下三重淚, 遠(yuǎn)去黃淮無禹同。 倚門三辭只為公, 林海春風(fēng)凱歌鳴。 聽聞涂...
    荷軒畫雪閱讀 358評論 1 2
  • 第十一章(一)umbrella什么都不知道。他只記得FOX和FLLFFL爭吵了起來,然后就沒了下文——當(dāng)時他就是覺...
    汀雨S26閱讀 494評論 0 2