Time Edition Movement in javascript

Keywords: Javascript JSON JQuery

Front words

  Speed version JS motion Referring to speed, time changes with the change of distance, while JS movement refers to time, and speed changes with the change of distance. Comparatively speaking, the time version of JS sports is more commonly used. JQ animate It's the time movement. This article will give a detailed introduction to the time version of JS motion.

 

Speed Version Motion

Why is the speed version of JS easier to understand? This is due to timer setInterval. The easiest form of operation to think of is as follows

setInterval(function(){
    s = s + step
},30)

Every 30 ms, the increment of the distance by step actually determines the speed as the reference. How the value of step changes determines the form of motion. Take the simplest uniform motion as an example

<button id="btn">Start Sports</button>
<button id="reset">reduction</button>
<div id="test" style="height: 100px;width: 100px;position:absolute;left:0;"></div>
<script>
var timer;
reset.onclick = function(){history.go();}
btn.onclick = function(){
    timer = setInterval(function(){
        if(test.offsetLeft < 500){
            test.style.left = test.offsetLeft + 10 + 'px';
        }else{
            test.style.left = '500px';
            clearInterval(timer);
        }    
    },30);
}
</script>

The total distance is 500, every 30 ms, moving forward 10, equivalent to the speed of 1000/3 = 333.3. The final calculation shows that the cost time t=s/v=500/333.3=1.5s.

When the distance changes, it still moves at 333.3 speed, and the time changes accordingly. This is the speed version of motion.

 

Formula deduction

Let's introduce the time version of motion. Let's take the uniform motion as an example. Let's first assume several variables.

Distance c(change position)
Initial position B
Final position P
Duration D
Time t(time)
Velocity V

The above variables have the following equations

1. Final motion distance = final position - initial position

c = p - b

2. Final distance = velocity * duration

c = v * d

3. Current Motion Distance = Current Position - Initial Position

C (current) = P (current) - b

4. Current motion distance = speed*time

C (current) = v * t

Ultimately, it is expressed as the following function

P (current) = twin (t)

Therefore, the following formulas are obtained after sorting out.

P (current) = B + C (current) = b + v*t = b + c*t/d

The final result is

p = t * c / d + b

 

Uniform function

The time version of uniform motion is encapsulated in a name named linearMove.js Documents

if (!window.requestAnimationFrame) {
    requestAnimationFrame = function(fn) {
        setTimeout(fn, 17);
    };    
}
if (!window.cancelAnimationFrame) {
    window.cancelAnimationFrame = function(id) {
        clearTimeout(id);
    };
}
function getCSS(obj,style){
    if(window.getComputedStyle){
        return getComputedStyle(obj)[style];
    }
    return obj.currentStyle[style];
} 

function linearMove(obj,json,times,fn){
  //Get the current number of milliseconds
  var startTime = +new Date();  
  /*Get the initial value*/
  var iCur = {};
  for(var attr in json){
    if(attr == 'opacity'){
      //Round the value of the current value to remove the cause javascript In decimal count bug Existent tail
      iCur[attr] = Math.round(getCSS(obj,attr)*100);
    }else{
      //Remove units
      iCur[attr] = parseInt(getCSS(obj,attr));
    }
  }
  //Clear timer
  cancelAnimationFrame(obj.timer);
  obj.timer = requestAnimationFrame(function func(){
    //Obtain t,d parameter
    var d = times;
    var t = d - Math.max(0,startTime - (+new Date()) + d);
    for(var attr in json){
      /*Obtain the three parameters of b, c and p*/
      var b = iCur[attr];
      var c = json[attr]-iCur[attr];
      var p = t * ( c / d ) + b;
      /*Assignment*/
      if(attr == 'opacity'){
        obj.style.opacity = p / 100;
        obj.style.filter = 'alpha(opacity=' + p + ')';
      }else{
        obj.style[attr] = p + 'px';
      }  
    }
      obj.timer = requestAnimationFrame(func);
      /*After running the specified time*/
      if(t == d){
        //Clear timer
        cancelAnimationFrame(obj.timer);
        //Setting callback function
        fn && fn.call(obj);        
      }    
  });
} 

Next, call linearMove.js encapsulated by yourself to make an example

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <title>Document</title>
</head>
<body>
<button id="btn">Start Sports</button>
<button id="reset">reduction</button>
<div id="test1" style="height: 100px;width: 100px;background: pink;position:absolute;left:0;"></div>
<div id="test2" style="height: 100px;width: 100px;background: blue;position:absolute;top:250px;left:0;"></div>
<script src="http://files.cnblogs.com/files/xiaohuochai/linearMove.js"></script>
<script>
reset.onclick = function(){history.go();}
btn.onclick = function(){
   linearMove(test1,{width:400,height:200,left:100},500,function(){
      linearMove(test2,{width:300},500);
   });
   linearMove(test2,{left:200},500)
}
</script>
</body>
</html>

 

Tween algorithm

Tween is a motion algorithm from flash. It contains various classical motion formulas for animation. The detailed list is as follows.

Linear: Linear uniform motion effect;
Quadratic(Quad): Slow motion of the quadratic (t^2);
Cubic: cubic slow motion (t^3);
Quartic(Quart): the slow motion of the fourth power (t^4);
Quintic(Quint): The quintic slow motion (t^5);
Sinusoidal(Sine): Slow motion of sinusoidal curve (sin(t));
Exponential(Expo): Slow movement of exponential curve (2^t);
Circular(Circ): Slow motion of circular curve (sqrt(1-t^2));
Elastic: The sinusoidal curve of exponential decay slows down;
Back: Over the range of cubic slowing ((s+1)*t^3 - s*t^2);
Bounce: The rebound of exponential decay is slow.

Each effect is divided into three slow-moving modes.

easeIn: Slow acceleration from 0, that is, slow first and then fast.
easeOut: Slow down to 0, that is, first fast and then slow.
easeInOut: The first half accelerates from 0, and the second half slows down to 0.

All these slow-down algorithms can not be separated from the following four parameters, t, b, c, d, which means as follows:

t Current time
b Initial position
c distance (change position)
d duration

The detailed algorithm of tween is as follows

// Tween class
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;
        }
    }
};

The streamlined version of the tween algorithm is as follows

var Tween = {
    linear: function (t, b, c, d){  //Uniform speed
        return c*t/d + b;
    },
    easeIn: function(t, b, c, d){  //Acceleration curve
        return c*(t/=d)*t + b;
    },
    easeOut: function(t, b, c, d){  //Deceleration curve
        return -c *(t/=d)*(t-2) + b;
    },
    easeBoth: function(t, b, c, d){  //Accelerated deceleration curve
        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){  //Acceleration curve
        return c*(t/=d)*t*t*t + b;
    },
    easeOutStrong: function(t, b, c, d){  //Deceleration curve
        return -c * ((t=t/d-1)*t*t*t - 1) + b;
    },
    easeBothStrong: function(t, b, c, d){  //Acceleration and deceleration curve
        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){  //Sinusoidal attenuation curve (elastic involution)
        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){    //Sinusoidal enhancement curve (elastic gradual)
        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){     //Backward acceleration
        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;  //Retraction distance
        }
        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){    //Shock Absorption of Balloon (Balloon Progressing)
        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;
    }
}

 

JQ extension

By default, JQ has only two forms of motion, linear and swing

jQuery.easing = {
    linear: function( p ) {
        return p;
    },
    swing: function( p ) {
        return 0.5 - Math.cos( p * Math.PI ) / 2;
    },
    _default: "swing"
};

The motion form of JQ can be extended by using tween algorithm. The functions of motion form in JQ source code are as follows.

this.pos = eased = jQuery.easing[ this.easing ](
                percent, this.options.duration * percent, 0, 1, this.options.duration
            );

As you can see, it has five parameters, corresponding to p, t, d, c and D in the tween algorithm, so it is necessary to modify the parameters in the tween algorithm.

<script src="http://cdn.bootcss.com/jquery/1.12.4/jquery.min.js"></script>
<script>
;(function($){
   $.extend(jQuery.easing,{
    linear: function (p,t, b, c, d){  //Uniform speed
      return c*t/d + b;
    },
    easeIn: function(p,t, b, c, d){  //Acceleration curve
      return c*(t/=d)*t + b;
    },
    easeOut: function(p,t, b, c, d){  //Deceleration curve
      return -c *(t/=d)*(t-2) + b;
    },
    easeBoth: function(p,t, b, c, d){  //Accelerated deceleration curve
      if ((t/=d/2) < 1) {
        return c/2*t*t + b;
      }
      return -c/2 * ((--t)*(t-2) - 1) + b;
    },
    easeInStrong: function(p,t, b, c, d){  //Acceleration curve
      return c*(t/=d)*t*t*t + b;
    },
    easeOutStrong: function(p,t, b, c, d){  //Deceleration curve
      return -c * ((t=t/d-1)*t*t*t - 1) + b;
    },
    easeBothStrong: function(p,t, b, c, d){  //Acceleration and deceleration curve
      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(p,t, b, c, d, a, p){  //Sinusoidal attenuation curve (elastic involution)
      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(p,t, b, c, d, a, p){    //Sinusoidal enhancement curve (elastic gradual)
      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(p,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(p,t, b, c, d, s){     //Backward acceleration
      if (typeof s == 'undefined') {
         s = 1.70158;
      }
      return c*(t/=d)*t*((s+1)*t - s) + b;
    },
    backOut: function(p,t, b, c, d, s){
      if (typeof s == 'undefined') {
        s = 3.70158;  //Retraction distance
      }
      return c*((t=t/d-1)*t*((s+1)*t + s) + 1) + b;
    }, 
    backBoth: function(p,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(p,t, b, c, d){    //Shock Absorption of Balloon (Balloon Progressing)
      return c - this['bounceOut'](p,d-t, 0, c, d) + b;
    },       
    bounceOut: function(p,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(p,t, b, c, d){
      if (t < d/2) {
        return this['bounceIn'](p,t*2, 0, c, d) * 0.5 + b;
      }
      return this['bounceOut'](p,t*2-d, 0, c, d) * 0.5 + c*0.5 + b;
    }
  }); 
})(jQuery);
</script>

Next, the extended JQ plug-in is used for JQ's custom movement.

<button id="btn">Start Sports</button>
<button id="reset">reduction</button>
<div id="test" style="height: 100px;width: 100px;background-color: pink;position:absolute;left:0;"></div>
<script>
reset.onclick = function(){history.go();}
btn.onclick = function(){
   $(test).animate({width:300},1000,'bounceBoth')
} 
</script>

 

Tween function

Based on the above tween algorithm, we encapsulate all the motion forms in tween, named as tweenMove.js

if (!window.requestAnimationFrame) {
    requestAnimationFrame = function(fn) {
        setTimeout(fn, 17);
    };    
}
if (!window.cancelAnimationFrame) {
    window.cancelAnimationFrame = function(id) {
        clearTimeout(id);
    };
}
function getCSS(obj,style){
    if(window.getComputedStyle){
        return getComputedStyle(obj)[style];
    }
    return obj.currentStyle[style];
} 
// Tween class
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;
        }
    }
};  
function tweenMove(obj,json,times,fx,fn){
  //Get the current number of milliseconds
  var startTime = +new Date();  
  /*Get the initial value*/
  var iCur = {};
  for(var attr in json){
    if(attr == 'opacity'){
      //Round the value of the current value to remove the cause javascript In decimal count bug Existent tail
      iCur[attr] = Math.round(getCSS(obj,attr)*100);
    }else{
      //Remove units
      iCur[attr] = parseInt(getCSS(obj,attr));
    }
  }
  //Clear timer
  cancelAnimationFrame(obj.timer);
  obj.timer = requestAnimationFrame(function func(){
    //Obtain t,d parameter
    var d = times;
    var t = d - Math.max(0,startTime - (+new Date()) + d);
    for(var attr in json){
      /*Obtain the three parameters of b, c and p*/
      var b = iCur[attr];
      var c = json[attr]-iCur[attr];
      var fxArr = fx.split('-');
      if(fxArr.length == 2){
        var p = Tween[fxArr[0]][fxArr[1]](t,b,c,d);
      }else{
        var p = Tween[fx](t,b,c,d);
      }     
      /*Assignment*/
      if(attr == 'opacity'){
        obj.style.opacity = p / 100;
        obj.style.filter = 'alpha(opacity=' + p + ')';
      }else{
        obj.style[attr] = p + 'px';
      }  
    }
      obj.timer = requestAnimationFrame(func);
      /*After running the specified time*/
      if(t == d){
        //Clear timer
        cancelAnimationFrame(obj.timer);
        //Setting callback function
        fn && fn.call(obj);        
      }    
  });
} 

The following is an example demonstration

<button id="btn">Start Sports</button>
<button id="reset">reduction</button>
<div id="test1" style="height: 100px;width: 100px;background-color: pink;position:absolute;left:0;"></div>
<div id="test2" style="height: 100px;width: 100px;background-color: blue;position:absolute;left:300px;"></div>
<script src="http://files.cnblogs.com/files/xiaohuochai/tweenMove.js"></script>
<script>
reset.onclick = function(){history.go();}
btn.onclick = function(){
   tweenMove(test1,{width:300,height:200},500,'Bounce-easeInOut',function(){
    tweenMove(test2,{width:300},500,'Linear');
   });
   tweenMove(test2,{left:400},500,'Linear');
   
}
</script>

 

Tween demo

Following is an encapsulated motion framework tweenMove.js Demonstration of all motion forms in tween algorithm

Posted by tripleM on Sat, 01 Jun 2019 11:59:50 -0700