[英]requestAnimationFrame [now] vs performance.now() time discrepancy
假設:rAF now
時間是在所有回調都被觸發時計算的。 因此,在調用該幀的第一個回調之前發生的任何阻塞now
都不會影響rAF並且它是准確的 - 至少對於第一次回調而言。
在觸發rAF集之前進行的任何performance.now()測量應該早於now
rAF。
測試:記錄before
( 任何事情發生before
的基線時間)。 設置下一個rAF。 now
比較rAF和實際performance.now()
before
看看它們有多么不同。
預期成績:
var before = performance.now(), frames = ["with blocking", "with no blocking"], calls = 0; requestAnimationFrame(function frame(rAFnow) { var actual = performance.now(); console.log("frame " + (calls + 1) + " " + frames[calls] + ":"); console.log("before frame -> rAF now: " + (rAFnow - before)); console.log("before frame -> rAF actual: " + (actual - before)); if (++calls < frames.length) { before = actual; requestAnimationFrame(frame); } }); // blocking for (var i = 0, l = 0; i < 10000000; i++) { l += i; }
觀察:當幀開始之前存在阻塞時,即使對於第一幀,rAF now
時間有時也是不正確的。 有時,第一幀now
實際上是比before
記錄的時間更早的時間。
無論是否在幀之前發生阻塞,幀內時間rAFnow
都會比之前的幀before
時間before
即在我進行第一次測量后設置rAF時。 這也可以在沒有任何阻塞的情況下發生,盡管這種情況很少見。
(我在大多數時間都在第一個阻塞幀上出現時間錯誤。在其他阻塞幀上出現問題的情況比較少見,但如果你嘗試運行幾次,偶爾會發生這種情況。)
通過更廣泛的測試,我發現在回調之前阻塞的不良時間:100幀中的1%,沒有阻塞:來自~400幀的0.21645021645021645%,似乎是由用戶打開窗口或其他一些潛在的CPU密集型操作引起的。
所以這是相當罕見的,但問題是這根本不會發生。 如果你想用它們做有用的事情,模擬時間,動畫等,那么你需要那些時間才有意義。
我已經考慮到了人們所說的話,但也許我仍然不理解事情的運作方式。 如果這是所有的規格,我會喜歡一些偽代碼來鞏固它在我的腦海里。
更重要的是,如果有人對如何解決這些問題有任何建議,那將是非常棒的。 我唯一能想到的是自己的performance.now()
測量每一幀並使用它 - 但它看起來有點浪費,讓它在每一幀上有效地運行兩次,在任何觸發事件之上等等。
傳遞給requestAnimationFrame()
回調的時間戳是動畫幀開始的時間。 在同一幀期間調用的多個回調都接收相同的時間戳。 因此,如果performance.now()
在參數值之前返回一個時間,那將是非常奇怪的,但在此之后它並不是真的很奇怪。
當用戶代理是一種用於與時間戳的文檔文件現在運行的動畫幀的回調,它必須執行下列步驟:
如果文檔對象的hidden屬性返回的值為true,則中止這些步驟。 [PAGE-VISIBILITY]
讓回調成為文檔動畫幀回調列表中的條目列表,按照它們添加到列表中的順序排列。
將文檔的動畫幀回調列表設置為空列表。
對於回調中的每個條目,按順序:調用Web IDL回調函數, 現在作為唯一參數傳遞,如果拋出異常,則報告異常。
所以你已經為下一個動畫幀注冊了一個回調(假設只有一個)。 勾選滴答滴答,BOOM,該動畫幀的發生時間:
performance.now()
並將其與作為參數傳入的now值進行比較。 因為在步驟1和步驟6之間可能會經過一段短暫但不可忽略的時間,所以performance.now()
的返回值可能表示已經過了幾微秒,甚至多於幾微秒。 這是完全正常的行為。
我在chrome上遇到了同樣的問題,其中對performance.now ()
調用返回的值高於傳遞給window.requestAnimationFrame ()
后續回調的now
值。
我的解決方法是在第一個window.requestAnimationFrame ()
而不是performance.now ()
設置before
使用now
傳遞給回調的。 似乎只使用兩個函數中的一個來測量時間可以保證值的進步。
我希望這可以幫助其他任何遭受這個bug的人。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.