摘要:動畫原文通常,框架會為你處理動畫。整個的動畫過程被分成了很小的步驟,每一個步驟被定時器調用。因為定時器的周期非常短,所以動畫看起來是連續的。已經過去的動畫時間作為分子,計算每一幀通過公式。線性的使動畫以固定的速度進行。
動畫
原文:http://javascript.info/tutori...
通常,框架會為你處理動畫。但是,你可能想知道僅僅用javascript怎么來實現動畫,和可能出現的一些問題。理解這項技術對于創建復雜的動畫是很有幫助的,即使在框架的幫助下。
動畫基礎javascript的動畫是通過周期性的改變DOM元素的style 或者 canvas 的對象。
整個的動畫過程被分成了很小的步驟(step),每一個步驟被定時器調用。因為定時器的周期非常短,所以動畫看起來是連續的。
偽代碼:
var id = setInterval(function(){ /*當前顯示幀*/ if(/*完成*/) clearInterval(id) }, 10)
上面代碼每一幀的間隔是 10ms ,意味著每秒鐘有100幀。
在大多數的javascript框架中 10-15ms的delay是默認的。越短的延時讓動畫看起來更加流暢,但是只有在瀏覽器足夠快的時候,每一步的動畫才會準時運行。
如果動畫需要許多計算,CPU可能會100%的負載,動畫就會變得遲緩。這種情況下,delay就應該被增加。例如,delay 40ms 就是每秒25幀,接近24幀的電影標準。
setInterval 而不是用 setTimout(其實在現代瀏覽器中大多使用requestAnimationFrame)例子我們使用setInterval,而不是遞歸的使用setTimeout,是因為我們想要一幀一個delay,而不是所有幀之間有一個固定的delay.查閱Understanding timers: setTimeout and setInterval來了解setInterval和遞歸的setTimeout之間到底有什么不同。(譯者:經測試最新的chrome > 56中,setInterval的行為跟本文中描述的不同。當函數執行時間超過了delay時間,下一個函數不會馬上運行,仍然會等一個delay的間隔,再執行。但本文仍有參考價值)
例如,一個元素移動通過改變element.stye.left從0到100px。每10ms改變1px。
在新的窗口打開
動畫重構為了讓動畫更加通用,我們介紹下面的一些參數:
delay
??每一幀之間的間隔(ms).例如,10ms
duration
??整個動畫完成需要的時間(ms)。例如:1000ms
當動畫開始的時候,我們也可以用:
start ??動畫開始的時間,start = new Date
動畫過程的核心,每一幀我們需要計算:
timePassed
??從動畫開始所經過的時間(ms)。
??從0到動畫(duration)結束.但是偶爾可能會超過結束時間,因為瀏覽器的計時器并不準確。
progress
已經過去的動畫時間作為分子,計算每一幀通過公式timePassed/duration。值得范圍通常是0到1。
例如,progress的值為0.5就是說動畫時間(duration)已經過去了一半。
delta(progress)
一個返回當前動畫進度的函數。
例如,我們讓高度屬性從0%變化到100%。
我們可以讓動畫均勻的顯示,這樣動畫進度看起來就是線性的。
Mapping:
->progress = 0 -> height = 0%
->progress = 0.2 -> height = 20%
->progress = 0.5->height = 50%
->progress = 0.8 -> height = 80%
->progress = 1 -> height = 100%
但是我們可能想讓動畫緩慢的開始然后再加速。這樣的話經過一半的動畫時間高度可能只有25%
,然后逐漸加速到100%。
Mapping:
->progress = 0 -> height = 0%
->progress = 0.2 -> height = 4%
->progress = 0.5->height = 25%
->progress = 0.8 -> height = 64%
->progress = 1 -> height = 100%
delta(progress) 是一個映射動畫進度增量的函數,
動畫進度通常是0到1之間的一個數字。
這篇文章會用一些例子進一步討論幾種增量函數
step(delta)
這個函數是實際上用來做這件事的函數。
它計算出增量的結果并且應用它。
對于這個高度的例子,他們可能是:
function state(delta) { elem.style.height = 100*delta + "%" }
到現在為止幾個重要的參數是:
->?delay是setInterval的第二個參數。
->?duration是動畫完成需要的時間。
->?progress是動畫已經經過的時間,除以duration使它的值在0到1之間。
->?delta通過當前的時間,計算當前的動畫進度。
->?step做了視覺上(?)的工作。它獲得當前的動畫進度,并且把它應用在元素上。
讓我們把上面討論的簡單的寫成一個可擴展的動畫核心。
下面的動畫函數執行時間管理并且把工作分配給delta和step:
function animate(opts) { var start = new Date; var id = setInterval(function(){ var timePassed = new Date - start; var progress = timePassed / opts.duration; if(progress > 1) progress = 1; var delta = opts.delta(progress) opts.step(delta) if(progress == 1) { clearInterval(id) } }, opts.delay || 10) }
參數對象應該包含以下的一些動畫屬性:
->?delay
->?duration
->?function delta
->?function step
這個算法完全遵循上面的描述
讓我們基于這個來創建一個移動的動畫
function move(element, delta, duration){ var to = 500; animate({ delay: 10, duration: duration || 1000, delta: delta, step: function(delta){ element.style.left = to * delta + "px" } }) }
它把工作指派給animate,給animate傳入了delay,用戶提供的duration, delta, 和 step。
delta = function(p) { return p}
??意味著動畫進程一直是均勻的
step
??用一個簡單的公式映射0..1,delta返回一個進度值 0..to。把這些結果應用到element.style.left。
用法:
數學,進度增量函數
動畫就是是根據給定的規則,一直改變屬性。在javascript動畫中,這個規則就是delta函數來實現的。
不同的delta使動畫的速度,加速度和其他的參數表現出各種各樣的形式。
數學公式通常被用在這里。但是它們對于只做web編程和忘記學校里的數學的人來說,可能很陌生。在這個章節,我們將瀏覽很多的受歡迎的公式并看一下它們是如何工作的。
動畫運動的例子,提供不同的delta.
線性 delta
function linear(progress){ return progress; }
水平方向指的是時間進度,垂直方向指的是動畫進程。
我們已經能看見了。線性的delta使動畫以固定的速度進行。
Power of n
也是一個簡單的例子。delta是progress的n次方。例如2次,3次方等。
例如2次方
function quad(progress) { return Math.pow(progress, 2) }
增加加速度的影響。例如,下面這個圖片是5次方。
Circ: 圓的一部分
function circ(progress) { return 1 - Math.sin(Math.acos(progress)) }
Back: the bow function
這個函數向弓一樣工作:首先我們"拉開工,然后發射出去"。
不像先前的函數,它會依賴于一個附加的參數x,這就是“彈性系數”。
它定義了“拉弓”的距離。
代碼是:
function back(progress, x) { return Math.pow(progress, 2) * ((x + 1) * progress - x) }
圖像x=1.5
bounce(彈跳)
想象一下我們釋放一個球,它掉在地上,然后彈跳幾次,最后停止。
bounce事實上做了相反的事情。屬性將會一直改變知道它達到目標點。
這個函數比之前要復雜一些,也沒有簡單的數學公式。
function bounce(progress) { for(var a = 0, b=1, result; 1; a+=b, b /= 2) { if (progress >= (7-4*a) / 11){ return -Math.pow(11 - 6 * a - 11 * progress) / 4, 2) + Math.pow(b, 2) } } }
*這段代碼曲子 MooTools.FX.Transitions.據我所知,仍然有其他實現bounce的算法。
Elastic 彈性
這個函數也依賴于額外的參數x,x定義了初始范圍。
function elastic(progress, x){ return Math.pow(2, 10 * (progress - 1)) * Math.cos(20 * Math.PI * x/3 *progress) }
圖像 x=1.5
在這個例子中,為了讓動畫更加平滑,時間是2s.
反向函數(Reverse functions)
一個javascript框架經常會提供的一種delta函數。
它們的直接使用被稱作 easeIn.
偶爾的時候,需要以時間倒退的方式來展示動畫。這就叫做easeout 被"time-reversing"delta來實現。
未完待續
第一次翻譯點東西,質量不好,主要是做記錄用。里面有很多比較"術語"的,不好翻,最好看原文。后面我也會繼續修改。
文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規行為,您可以聯系管理員刪除。
轉載請注明本文地址:http://specialneedsforspecialkids.com/yun/81899.html
摘要:前端日報精選如何優雅的編寫代碼深入理解內部機制專題之函數組合年月個有趣的和庫最經典的前端面試題之一,你能答出什么幺蛾子中文翻譯深入理解響應式原理掘金譯與和交互掘金箭頭函數使用禁忌技術棧耕耘助力美團點評前端進階之路前端模塊 2017-09-01 前端日報 精選 如何優雅的編寫 JavaScript 代碼深入理解 Node.js Stream 內部機制JavaScript專題之函數組合20...
摘要:巧前端基礎進階全方位解讀前端掘金我們在學習的過程中,由于對一些概念理解得不是很清楚,但是又想要通過一些方式把它記下來,于是就很容易草率的給這些概念定下一些方便自己記憶的有偏差的結論。 計算機程序的思維邏輯 (83) - 并發總結 - 掘金從65節到82節,我們用了18篇文章討論并發,本節進行簡要總結。 多線程開發有兩個核心問題,一個是競爭,另一個是協作。競爭會出現線程安全問題,所以,本...
摘要:巧前端基礎進階全方位解讀前端掘金我們在學習的過程中,由于對一些概念理解得不是很清楚,但是又想要通過一些方式把它記下來,于是就很容易草率的給這些概念定下一些方便自己記憶的有偏差的結論。 計算機程序的思維邏輯 (83) - 并發總結 - 掘金從65節到82節,我們用了18篇文章討論并發,本節進行簡要總結。 多線程開發有兩個核心問題,一個是競爭,另一個是協作。競爭會出現線程安全問題,所以,本...
摘要:前端日報精選譯發布了王躍關于微信小程序的技術,也許你想錯了細說中的瀏覽器頁面渲染工作原理淺析騰訊前端團隊社區中文第期安息吧,長存譯借助函數完成可組合的數據類型軟件編寫第十部分掘金對象與原型掘金技術周刊期知乎專欄是真正的語言 2017-10-16 前端日報 精選 [譯]Vue 2.5 發布了王躍:關于微信小程序的技術,也許你想錯了細說Web API中的Blobchrome瀏覽器頁面渲染工...
閱讀 1357·2021-10-09 09:44
閱讀 1440·2021-09-28 09:36
閱讀 15927·2021-09-22 15:55
閱讀 1239·2021-09-22 15:45
閱讀 2199·2021-09-02 09:48
閱讀 2783·2019-08-29 17:19
閱讀 2296·2019-08-29 10:54
閱讀 906·2019-08-23 18:40