JavaScript 動畫我們可以使用 JavaScript 來創(chuàng)建動態(tài)的圖像。實例 按鈕動畫 利用兩個不同的事件來驅(qū)動兩個相應的函數(shù),來切換兩張對應的圖片以創(chuàng)造出動畫效果。
今天,小學生以自己淺薄的見地,在前輩大能的基礎(chǔ)上寫這篇文章,希望給大家打開一扇窺探JavaScript(以下簡稱JS)動畫的窗戶。
JS如何制造出動畫效果?
結(jié)合瀏覽器提供的 setInterval 或 setTimeout API,高頻改變DOM元素的一些屬性,即可創(chuàng)造一個肉眼可見的動畫效果。一個看起來非常流暢的JS動畫除了需要良好的變換算法外,與其執(zhí)行宿主也是非不開的。程序?qū)懙迷俸茫绻麨g覽器過于老舊,電腦CPU性能低下,也會出現(xiàn)卡頓,甚至卡死。
執(zhí)行一個動畫函數(shù)對于瀏覽器來說是個苦差,設(shè)置動畫一幀為多長時間才能既流暢又不損耗性能呢?瀏覽器不會傻到進行一個DOM操作,就去渲染一次頁面。它會把一個周期內(nèi)所有的DOM操作整合起來,統(tǒng)一進行一次渲染。這個周期大約在16.7ms左右,不同瀏覽器間會有幾毫秒的差異。SetTimeout的第二個參數(shù)設(shè)置為1000/60是比較合乎情理的做法。不過了解過SetTimeout運行機制的都會清楚,這個時間并不可靠,其根據(jù)實際情況會有些許甚至相當大的延遲。那么有沒有這樣一個API?我不想知道你瀏覽器到底多久渲染一次,反正你渲染的時候給我的動畫執(zhí)行一幀就行了。答案是有,requestAnimationFrame,可以讓函數(shù)隨著瀏覽器渲染執(zhí)行,并且執(zhí)行時機是可靠的。注意,這個方法在現(xiàn)在瀏覽器及IE10+才被支持。
現(xiàn)在可以封裝起一個簡單的requestAnimationFrame,下面的例子中將會使用到它。
- window.requestAnimFrame = (function(){
- return window.requestAnimationFrame ||
- window.webkitRequestAnimationFrame ||
- window.mozRequestAnimationFrame ||
- function( callback ){
- window.setTimeout(callback, 1000 / 60);
- };
- })();
更加詳細的封裝可以在張鑫旭的博客中看到:張鑫旭:requestAnimFrame。下面讓我們繼續(xù)。
動畫函數(shù)的編寫
有了requestAnimationFrame,下面該考慮一下如何讓寫動畫函數(shù)了。一般來說我們會給出一個毫秒級的during值,限制這個動畫必須要在這個時間內(nèi)完成。下面以實現(xiàn)一個小球從離頁面左側(cè)100px處勻速運動到800px處為例,編寫一個動畫函數(shù):戳我查看DEMO。
- var ele = document.getElementById("block");
- var start = Date.now();//獲取動畫開始的時間。
- var during = 1000; //此動畫要在1秒內(nèi)執(zhí)行完。
- var p=0;//動畫完成度 從0-1;
- requestAnimationFrame(function f(){
- if(p>=1){ ele.style.left="800px";}//如果發(fā)現(xiàn)動畫已經(jīng)執(zhí)行完,將元素置到終點。
- else{
- p=(Date.now()-start)/during;
- ele.style.left=100+700*p+"px"; //從100px開始,勻速向右移動,共移動700px;
- requestAnimationFrame(f);
- }
- })
上面函數(shù)中有一個關(guān)鍵變量:p,即percentage,我們可以稱它為動畫的完成度,它是根據(jù)當前時間計算得出的,并且從動畫開始后,會從0~1勻速漸變。當其為1時,表示整個動畫執(zhí)行完畢。在這個函數(shù)中,讓p乘以要運動的長度700,便會得到一個0-700勻速變化的值,將其加上開始的100,便可模擬小球從100px處勻速移動到800px處。
設(shè)想一下,假如上面紅色標出的運動方程改為“ele.style.left=100+700*p*p+"px"”呢?p以二次方漸增,小球向右移動的速度會越來越快。是的,稍加修改便可實現(xiàn)一個勻加速運動的小球。
下面,我們就是要針對p來做文章。
Tween算法及緩動效果
下面我將列舉一些常用的緩動算法,根據(jù)這些算法去修改上面勻速運動函數(shù)的運動方程,即可實現(xiàn)很贊的動畫效果。
1.2次方緩動: p*p
2.3次方緩動: p*p*p
3.4次方緩動: p*p*p*p
4.5次方緩動: p*p*p*p*p
5.正弦曲線緩動: Math.sin(p*Math.PI/2)
6.指數(shù)曲線緩動: Math.pow(2,10*(p-1))
7.圓形曲線緩動: Math.sqrt(1-(p-1)*(p-1))
8.超范圍三次方: p*p*(2.70158*p-1.70158)
驗證一下吧,比如我現(xiàn)在想實現(xiàn)一個小球向右運動,有一個向左蓄力的動畫,我只要把第一個demo的運動方程改為“ele.style.left=100+700*p*p*(2.70158*p-1.70158)+"px"”就行了,看看效果吧:戳我查看DEMO。
其實,每種緩動算法都可以進化為三種緩動方式,分別為ease-in(先慢后快),ease-out(先快后慢),ease-in-out(先慢后快再慢)。
以2次方緩動為例,它本身就是一個勻加速的過程,所以ease-in就是p*p。其ease-out為-(p*(p-2))。關(guān)于緩動方式,像陽光一樣在他的博客中有更加詳細的解釋:JavaScript動畫、運動算法詳細解釋與分析。
接下來要放大招了,關(guān)于緩動的整合DEMO,戳我吧。
JS動畫可以做什么?
除了上面的緩動效果,利用常見的數(shù)學公式還可以實現(xiàn)一些周期性運動效果,例如小球勻速圓周運動,小球勻速簡諧振動等,如果感興趣請猛戳DEMO。
那么JS動畫可以做什么呢?這就需要發(fā)揮我們的個人想象力了,上面的DEMO大部分都在操控單一的屬性,比如left,讓DOM元素發(fā)生位移。事實上在運動方程中,元素的任何style都可以被漸變。試想一下,設(shè)置一個DOM元素的opacity從0~1進行2次方緩動,便是一個簡單的jQuery fadeOut函數(shù);讓一個DOM元素高度從無到有,便是一個簡單的jQuery slideDown函數(shù)。更加不要忘記的是,在動畫過程中不僅僅可以操作一項屬性,這為動畫帶來了無限的可能性,事情變得越來越有趣了:DEMO:一個從小到大變化的球。
再試想一下,使用CSS3屬性,例如box-shadow,transform,作出的效果必將會更加絢麗。
總結(jié)
上面提到使用CSS3屬性,其實如果這個瀏覽器支持CSS3屬性的話,完全沒有必要使用JS來做這件事。CSS3自有Animation動畫屬性,可以簡單快捷地實現(xiàn)酷炫的動畫效果,并且可以啟用GPU加速。美中不足的是僅現(xiàn)代瀏覽器支持。JS實現(xiàn)動畫勝在可以兼容低版本瀏覽器,但是其效果一般(僅限于普通意義上的動畫,不含canvas之類的)。
動畫僅僅是JS操作DOM魅力之冰山一角,而數(shù)學與計算機總是能碰撞出耀眼的火花。繼續(xù)學習JS吧,這是一門神奇的語言,同時也應該了解一些數(shù)學知識,往往能夠為解決事情帶來捷徑。
以上所述就是本文的全部內(nèi)容了,希望大家能夠喜歡。
新聞熱點
疑難解答
圖片精選