javascript中的緩動(dòng)效果實(shí)現(xiàn)程序
常見(jiàn)的動(dòng)畫(huà)有四種類型,介紹一下:
linear:線性動(dòng)畫(huà),即勻速
easeIn:速度從小到大,即淡入
easeOut :速度從大到小,即淡出
easeInOut:開(kāi)始時(shí)速度從小到大,結(jié)束時(shí)速度從大到小,即淡入淡出
其實(shí)說(shuō)到緩動(dòng),就不得不提Robert Penner,他發(fā)明了N多緩動(dòng)公式,舉個(gè)例子
我還是解釋一下吧:
設(shè)當(dāng)前變化量為X,則
t / d = X / c,所以X = c * t / d,然后X + b就可以獲得當(dāng)前屬性值
再看一個(gè)稍復(fù)雜的:
這個(gè)有淡入效果,也就是說(shuō)動(dòng)畫(huà)開(kāi)始時(shí),值的變化量從小到大。
可以發(fā)現(xiàn)兩者唯一的區(qū)別就是 t / d 和 (t /= d) * t,剛才說(shuō)了t / d是一個(gè)>=0 && <=1的比值,暫取名為a,而(t /= d) * t就相當(dāng)于Math.pow(a, 2)。
為什么要平方呢?
1. 首先a >= Math.pow(a, 2)是肯定的
2. 每次調(diào)用函數(shù)時(shí),t / d 這個(gè)比值也是勻速變大的,比如第1次調(diào)用時(shí)是0.1(平方0.01),第2次調(diào)用時(shí)是0.2(平方0.04)等,那第10次調(diào)用時(shí),肯定是1沒(méi)錯(cuò)吧,這時(shí)候 c * 1 + b,動(dòng)畫(huà)就到此結(jié)束了
3. 第2點(diǎn)證明了比值越小,值的變化量就越小,比值越大,值的變化量就越大,如果不用平方而是三次方,那淡入效果就更明顯了。
樣式、結(jié)構(gòu)及公共函數(shù)如下:
<style>
#container {width:500px;height:100px;border:1px #d1d1d1 solid;position:relative;}
#drag {width:100px;height:100px;background:#369;position:absolute;left:0;top:0;}
</style>
<div id="container">
<div id="drag"></div>
</div>
<script type="text/javascript">
function $(id) {
return typeof id == 'string' ? document.getElementById(id) : id;
}
function getStyle(el,styleProp){
return el.currentStyle ? el.currentStyle[styleProp] : document.defaultView.getComputedStyle(el,null).getPropertyValue(styleProp);
}
</script>
首先,從最簡(jiǎn)單的入手:設(shè)定開(kāi)始位置和結(jié)束位置及步長(zhǎng),每次增加固定的值,直至終止條件
var timer = null;
var begin = 0, end = 400, step = 5;
var drag = $("drag");
function run() {
if((iLeft = parseInt(getStyle(drag,"left"))) < end){
drag.style.left = iLeft + step + "px";
}else{
clearInterval(timer);
}
}
var timer = setInterval(run, 20);
上面這種方法是勻速,每次運(yùn)動(dòng)的距離是固定的,下面來(lái)看另外一種實(shí)現(xiàn)方式:
var timer = null;
var begin = 0, end = 400;
var drag = $("drag");
function run() {
if((iLeft = parseInt(getStyle(drag,"left"))) < end){
var step = Math.ceil((400 - iLeft)/7);
drag.style.left = iLeft + step + "px";
}else{
clearInterval(timer);
}
}
var timer = setInterval(run, 20);
上面這種方式是通過(guò)當(dāng)前的位置距離目標(biāo)的距離來(lái)計(jì)算此次位移的步長(zhǎng)
在flash中有專門(mén)處理緩動(dòng)的類tween,轉(zhuǎn)化為javascript的代碼為:
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;
}
}
}
其中每種緩動(dòng)方式中對(duì)應(yīng)3種類型
easeIn:從0開(kāi)始加速的緩動(dòng);
easeOut:減速到0的緩動(dòng);
easeInOut:前半段從0開(kāi)始加速,后半段減速到0的緩動(dòng)
參數(shù)說(shuō)明:
t:當(dāng)前時(shí)間
b:初始值
c:變化量
d:持續(xù)時(shí)間
調(diào)用方式:
var timer = null;
var b=0,c=400,d=100,t=0;
var drag = $("drag");
function run() {
drag.style.left = Math.ceil(Tween.Circ.easeInOut(t,b,c,d)) + "px";
if(t<d){
t++;
}else{
clearInterval(timer);
}
}
var timer = setInterval(run, 20);
- JavaScript緩動(dòng)動(dòng)畫(huà)函數(shù)的封裝方法
- js實(shí)現(xiàn)緩動(dòng)動(dòng)畫(huà)
- JavaScript實(shí)現(xiàn)緩動(dòng)動(dòng)畫(huà)
- tween.js緩動(dòng)補(bǔ)間動(dòng)畫(huà)算法示例
- js實(shí)現(xiàn)帶緩動(dòng)動(dòng)畫(huà)的導(dǎo)航欄效果
- JS+HTML5手機(jī)開(kāi)發(fā)之滾動(dòng)和慣性緩動(dòng)實(shí)現(xiàn)方法分析
- javascript 45種緩動(dòng)效果 非常酷
- 讓div運(yùn)動(dòng)起來(lái) js實(shí)現(xiàn)緩動(dòng)效果
- javascript實(shí)現(xiàn)左右緩動(dòng)動(dòng)畫(huà)函數(shù)
相關(guān)文章
Js實(shí)現(xiàn)雙擊鼠標(biāo)自動(dòng)滾動(dòng)屏幕的示例代碼
這篇文章主要介紹了Js實(shí)現(xiàn)雙擊鼠標(biāo)自動(dòng)滾動(dòng)屏幕的示例代碼。需要的朋友可以過(guò)來(lái)參考下,希望對(duì)大家有所幫助2013-12-12javascript 偽數(shù)組實(shí)現(xiàn)方法
能通過(guò)Array.prototype.slice轉(zhuǎn)換為真正的數(shù)組的帶有l(wèi)ength屬性的對(duì)象。2010-10-10javascript實(shí)現(xiàn)日期時(shí)間動(dòng)態(tài)顯示示例代碼
這篇文章主要介紹了javascript實(shí)現(xiàn)日期時(shí)間動(dòng)態(tài)顯示示例代碼,頁(yè)面動(dòng)態(tài)顯示時(shí)間變化的方法有很多,本文為大家介紹下使用javascript的具體實(shí)現(xiàn),感興趣的朋友可以參考一下2015-09-09attachEvent的使用方法與傳遞參數(shù)[IE|firefox]
attachEvent的使用方法與傳遞參數(shù)[IE|firefox]...2007-05-05原生js+canvas實(shí)現(xiàn)驗(yàn)證碼
這篇文章主要為大家詳細(xì)介紹了原生js+canvas實(shí)現(xiàn)驗(yàn)證碼,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2020-11-11js移動(dòng)焦點(diǎn)到最后位置的簡(jiǎn)單方法
下面小編就為大家?guī)?lái)一篇js移動(dòng)焦點(diǎn)到最后位置的簡(jiǎn)單方法。小編覺(jué)得挺不錯(cuò)的,現(xiàn)在就分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧2016-11-11echarts圖表設(shè)置寬度100%結(jié)果為100px的解決辦法
在開(kāi)發(fā)一個(gè)前端項(xiàng)目時(shí)需要用到Element-ui的el-tabs組件和Echart開(kāi)源庫(kù),當(dāng)兩者嵌套使用時(shí),我給Echart中的圖表寬度設(shè)置為了100%,但是實(shí)際的寬度卻只有100px,這篇文章主要給大家介紹了關(guān)于echarts圖表設(shè)置寬度100%結(jié)果為100px的解決辦法,需要的朋友可以參考下2022-12-12javascript實(shí)現(xiàn)電腦和手機(jī)版樣式切換
這篇文章主要為大家詳細(xì)介紹了javascript實(shí)現(xiàn)電腦和手機(jī)版樣式切換,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2017-11-11RequireJS簡(jiǎn)易繪圖程序開(kāi)發(fā)
這篇文章主要為大家詳細(xì)介紹了使用RequireJS簡(jiǎn)易繪圖程序開(kāi)發(fā),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2016-10-10javascript中數(shù)組(Array)對(duì)象和字符串(String)對(duì)象的常用方法總結(jié)
這篇文章主要介紹了javascript中數(shù)組(Array)對(duì)象和字符串(String)對(duì)象的常用方法,結(jié)合實(shí)例形式總結(jié)分析了javascript中關(guān)于數(shù)組和字符串的常用函數(shù)與使用技巧,需要的朋友可以參考下2016-12-12