如果您喜歡使用 requestAnimationFrame
,一定覺得繪製與螢幕重新整理頻率保持同步,就能產生高擬真度的動畫。此外,使用者切換至其他分頁時,還能節省 CPU 風扇噪音和電池電力。
不過,此 API 將有異動。傳遞至回呼函式的時間戳記,在從頁面開啟以來,從一般 Date.now()
(類似) 的時間戳記變更為高解析度的浮點毫秒測量值。如果您使用這個值,就必須按照下方說明更新程式碼。
提醒你,以下是我提到的:
// assuming requestAnimationFrame method has been normalized for all vendor prefixes..
requestAnimationFrame(function(timestamp){
// the value of timestamp is changing
});
如果您使用的是此處提供的通用 requestAnimFrame
輔助程式,則未使用時間戳記值。未關切。:)
為什麼要
原因何在?Well rAF 可讓您取得最適當的 60 fps 效能,而 60 fps 能轉換為每個畫格 16.7 毫秒。但若以整數毫秒為單位測量,代表我們可以將精確度設為 1/16,以便觀察及指定的所有內容。
如上所述,藍色長條代表在繪製新影格之前,必須處理所有工作最多的時間 (每秒 60 個影格)。您可能已經執行超過 16 個任務,但是整數毫秒卻只能以非常小的增量為單位進行排程和測量。這樣不夠好。
高解析度計時器能提供更精準的圖形來解決這個問題:
Date.now() // 1337376068250
performance.now() // 20303.427000007
目前可在 Chrome 中使用 window.performance.webkitNow()
這個高解析度計時器,且這個值通常與傳入 rAF 回呼的新引數值相等。等規格進一步通過標準後,此方法就會捨棄前置字元,並可透過 performance.now()
使用。
您也會發現,上述兩個值是不同數量的許多順序。performance.now()
是浮點數的測量值,因為特定網頁開始載入 (具體的 performance.navigationStart
)。
使用中
裁剪的主要問題是採用以下設計模式的動畫程式庫:
function MyAnimation(duration) {
this.startTime = Date.now();
this.duration = duration;
requestAnimFrame(this.tick.bind(this));
}
MyAnimation.prototype.tick = function(time) {
var now = Date.now();
if (time > now) {
this.dispatchEvent("ended");
return;
}
...
requestAnimFrame(this.tick.bind(this));
}
修正此問題的方法很容易...請擴充 startTime
和 now
,以便使用 window.performance.now()
。
this.startTime = window.performance.now ?
(performance.now() + performance.timing.navigationStart) :
Date.now();
這是相當簡單的實作,並未使用包含前置字串的 now()
方法,而且也假設 Date.now()
支援 (不在 IE8 中)。
特徵偵測
如果您並未使用上述模式,只是想找出您收到的回呼值類型,可以使用以下技巧:
requestAnimationFrame(function(timestamp){
if (timestamp < 1e12){
// .. high resolution timer
} else {
// integer milliseconds since unix epoch
}
// ...
查看 if (timestamp < 1e12)
是一項簡易的鴨肉測試,可用來瞭解我們正在處理的數量。嚴格說來,網頁必須持續開啟 30 年才有可能出現偽陽性,但是,我們無法測試其是否為浮點數 (而非下限為整數)。要求取得足夠的高解析度計時器,而且在特定時間點可以取得整數值。
這項變更預計會在 Chrome 21 版中生效,因此如果你已經充分利用這個回呼參數,請務必更新程式碼!