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