缓动公式总结

编程入门 行业动态 更新时间:2024-10-11 15:17:35

缓动<a href=https://www.elefans.com/category/jswz/34/1769303.html style=公式总结"/>

缓动公式总结

普通的加速减速是难以让人满意的,为了实现弹簧等让人眼花缭乱的效果必须动用缓动公式。我见过两套缓动公式,一套是早期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*************
//.htmlvar 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" οnclick="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 
参数类型说明
elelement必需,为页面元素
beginnumber必需,开始的位置
changenumber必需,要移动的距离
durationnumber可选,缓动效果持续时间,默认是500ms。建议取300~1000ms。
fieldstring必需,要发生变化的样式属性。请在top,left,bottom,right,width与height中选择。
ftpnumber可选,每秒进行多少帧动画,默认50帧,保证流畅播放。一些参考资料,日本动画1秒36帧,中国卡通24帧,赛车游戏60帧。
easefunction必需,缓动公式,参数为0~1之间的数。可参考我下面给出的45条公式。
onStartfunction可选,在开始时执行。
onEndfunction可选,在结束时执行。

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);elsereturn 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}

}

转载地址:.html

更多推荐

缓动公式总结

本文发布于:2024-02-14 03:34:37,感谢您对本站的认可!
本文链接:https://www.elefans.com/category/jswz/34/1761821.html
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,我们将在24小时内删除。
本文标签:公式

发布评论

评论列表 (有 0 条评论)
草根站长

>www.elefans.com

编程频道|电子爱好者 - 技术资讯及电子产品介绍!