js动画的一些计算公式 - Sincere_Xie - 博客园
每个函数都有四个参数:
1.t====> current time:当前时间.解释为:开始的步数(一般从0开始),预示着一段动画的开始.
2.b====>beginning value 初始值.解释为:开始量(开始的属性值)
3.c====>change in value 变化量.解释为属性值的改变量:结束位置的属性值 - 开始位置的属性值
4.d====>duration 持续时间.解释为:结束的步数(运动的总时间)
Tween公式 4个参数
t:current time(当前时间)
b:beginning value(初始值)
c: change in value(变化量)
d:duration(持续时间) return (目标点)
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;
},
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;
}
}
常见动画函数:
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;
},
strongEaseIn: function(t, b, c, d) {
return c * (t /= d) * t * t * t * t + b;
},
strongEaseOut: function(t, b, c, d) {
return c * ((t = t / d - 1) * t * t * t * t + 1) + b;
},
sineaseIn: function(t, b, c, d) {
return c * (t /= d) * t * t + b;
},
sineaseOut: function(t, b, c, d) {
return c * ((t = t / d - 1) * t * t + 1) + b;
}
};
js运动函数
$B.Tween = {
Linear: function(t, b, c, d) {
return c * t / d + b;
},
quadEaseIn: function(t, b, c, d) {
return c * (t /= d) * t + b;
},
quadEaseOut: function(t, b, c, d) {
return -c * (t /= d) * (t - 2) + b;
},
quadEaseInOut: function(t, b, c, d) {
if((t /= d / 2) < 1) return c / 2 * t * t + b;
return -c / 2 * ((--t) * (t - 2) - 1) + b;
},
cubicEaseIn: function(t, b, c, d) {
return c * (t /= d) * t * t + b;
},
cubicEaseOut: function(t, b, c, d) {
return c * ((t = t / d - 1) * t * t + 1) + b;
},
cubicEaseInOut: 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;
},
quartEaseIn: function(t, b, c, d) {
return c * (t /= d) * t * t * t + b;
},
quartEaseOut: function(t, b, c, d) {
return -c * ((t = t / d - 1) * t * t * t - 1) + b;
},
quartEaseInOut: 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;
},
quintEaseIn: function(t, b, c, d) {
return c * (t /= d) * t * t * t * t + b;
},
quintEaseOut: function(t, b, c, d) {
return c * ((t = t / d - 1) * t * t * t * t + 1) + b;
},
quintEaseInOut: 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;
},
sineEaseIn: function(t, b, c, d) {
return -c * Math.cos(t / d * (Math.PI / 2)) + c + b;
},
sineEaseOut: function(t, b, c, d) {
return c * Math.sin(t / d * (Math.PI / 2)) + b;
},
sineEaseInOut: function(t, b, c, d) {
return -c / 2 * (Math.cos(Math.PI * t / d) - 1) + b;
},
expoEaseIn: function(t, b, c, d) {
return(t == 0) ? b : c * Math.pow(2, 10 * (t / d - 1)) + b;
},
expoEaseOut: function(t, b, c, d) {
return(t == d) ? b + c : c * (-Math.pow(2, -10 * t / d) + 1) + b;
},
expoEaseInOut: 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;
},
circEaseIn: function(t, b, c, d) {
return -c * (Math.sqrt(1 - (t /= d) * t) - 1) + b;
},
circEaseOut: function(t, b, c, d) {
return c * Math.sqrt(1 - (t = t / d - 1) * t) + b;
},
circEaseInOut: 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;
},
elasticEaseIn: 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;
},
elasticEaseOut: 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);
},
elasticEaseInOut: 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;
},
backEaseIn: function(t, b, c, d, s) {
if(s == undefined) s = 1.70158;
return c * (t /= d) * t * ((s + 1) * t - s) + b;
},
backEaseOut: 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;
},
backEaseInOut: 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;
},
bounceEaseIn: function(t, b, c, d) {
return c - $B.Tween.bounceEaseOut(d - t, 0, c, d) + b;
},
bounceEaseOut: 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;
}
},
bounceEaseInOut: function(t, b, c, d) {
if(t < d / 2) return $B.Tween.bounceEaseIn(t * 2, 0, c, d) * .5 + b;
else return $B.Tween.bounceEaseOut(t * 2 - d, 0, c, d) * .5 + c * .5 + b;
}
}
$B.nameSpace = function() {
}
$B.tween2 = {
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 requestAnimFrame = (function() {
return window.requestAnimationFrame || window.webkitRequestAnimationFrame || window.mozRequestAnimationFrame || function(callback) {
window.setTimeout(callback, 1000 / 60);
};
})();
var easeInOutQuad = function(t, b, c, d) {
t /= d / 2;
if(t < 1) return c / 2 * t * t + b;
t--;
return -c / 2 * (t * (t - 2) - 1) + b;
};
export var animatedScrollTo = function(element, to, duration, callback) {
var start = element.scrollTop,
change = to - start,
animationStart = +new Date();
var animating = true;
var lastpos = null;
var animateScroll = function() {
if(!animating) {
return;
}
requestAnimFrame(animateScroll);
var now = +new Date();
var val = Math.floor(easeInOutQuad(now - animationStart, start, change, duration));
if(lastpos) {
if(lastpos === element.scrollTop) {
lastpos = val;
element.scrollTop = val;
} else {
animating = false;
}
} else {
lastpos = val;
element.scrollTop = val;
}
if(now > animationStart + duration) {
element.scrollTop = to;
animating = false;
if(callback) {
callback();
}
}
};
requestAnimFrame(animateScroll);
};
调用:
参数列表:操作的元素,滚动条要移动的位置,时间,回调函数
animatedScrollTo( //移动端:document.body.scrollTop PC端:document.documentElement.scrollTop
document.body,H,500,function(){
console.log('done!');
}
)

参数介绍:
obj
执行动画的元素cssJSON数值对,形式为“{属性名: 属性值}",指要执行动画的书序及其对应值
interval
属性每执行一次改变的时间间隔
speedFactor速度因子,使动画具有缓冲效果,而不是匀速不变(speedFactor为1)func执行完动画后的回调函数
注意:
必须为每一个元素分别添加一个定时器,否则会互相影响。
cur != css[arr]判断是否每一个属性已经达到目标值。只有所有属性都达到目标值,才会清除定时器,flag的作用是防止某个属性第一个达到目标值但还有其他属性没有达到目标值的情况下清除定时器。因此,在每次改变前初始化flag为true,只要遇到一个没有达到目标的属性,就将flag置为false,直至所有属性达到目标值才清除定时器。
属性值opacity的值有小数,所以需要特殊处理: Math.ceil(speed)和Math.floor(speed)以及* 100和 / 100操作。
function animate(obj, json, interval, sp, fn) {
clearInterval(obj.timer);
//var k = 0;
//var j = 0;
function getStyle(obj, arr) {
if(obj.currentStyle){
return obj.currentStyle[arr]; //针对ie
} else {
return document.defaultView.getComputedStyle(obj, null)[arr];
}
}
obj.timer = setInterval(function(){
//j ++;
var flag = true;
for(var arr in json) {
var icur = 0;
//k++;
if(arr == "opacity") {
icur = Math.round(parseFloat(getStyle(obj, arr))*100);
} else {
icur = parseInt(getStyle(obj, arr));
}
var speed = (json[arr] - icur) * sp;
speed = speed > 0 ? Math.ceil(speed): Math.floor(speed);
if(icur != json[arr]){
flag = false;
}
if(arr == "opacity"){
obj.style.filter = "alpha(opacity : '+(icur + speed)+' )";
obj.style.opacity = (icur + speed)/100;
}else {
obj.style[arr] = icur + speed + "px";
}
//console.log(j + "," + arr +":"+ flag);
}
if(flag){
clearInterval(obj.timer);
//console.log(j + ":" + flag);
//console.log("k = " + k);
//console.log("j = " + j);
//console.log("DONE");
if(fn){
fn();
}
}
},interval);
}
调用方式:
<script>
var move = document.getElementById("move").getElementsByTagName("li");
for(var i = 0; i < move.length; i ++){
move[i].onmouseover = function(){
var _this = this;
animate(_this, {width: 500, height: 200},10, 0.01, function(){
animate(_this, {width: 300, height: 200},10, 0.01);
});
}
}
</script>
iTween.easeType各个内容函数图展示:
linearTween

easeInQuad

easeOutQuad

easeInOutQuad

easeInCubic

easeOutCubic

easeInOutCubic

easeInQuart

easeOutQuart

easeInOutQuart

easeInQuint

easeOutQuint

easeInOutQuint

easeInExpo

easeOutExpo

easeInOutExpo

easeInCirc

easeOutCirc

easeInOutCirc

easeInSine

easeOutSine

easeInOutSine

easeInBack

easeOutBack

easeInOutBack

easeInElastio

easeOutElastio

easeInOutElastio

easeInBounce

easeOutBounce

easeInOutBounce
