[英]Multiple requestAnimationFrame performance
如果我正在做多個動畫,添加多個requestAnimationFrame
回調是否可以提高性能? 例子:
function anim1() {
// animate element 1
}
function anim2() {
// animate element 2
}
function anim3() {
// animate element 3
}
requestAnimationFrame(anim1);
requestAnimationFrame(anim2);
requestAnimationFrame(anim3);
或者它被證明比使用單個回調更糟糕:
(function anim() {
requestAnimationFrame(anim);
anim1();
anim2();
anim3();
}());
我問是因為我真的不知道幕后發生了什么,當您多次調用requestAnimationFrame
時是否會排隊回調?
我認為這些答案中的任何一個都沒有真正解釋我正在尋找的內容:“對 requestAnimationFrame 進行 n 次調用”得到去抖動(即每幀出列 1 個)或在下一幀中全部被調用。
當 requestAnimationFrame() 排隊的回調開始在單個幀中觸發多個回調 ( mdn )
這表明后者,可以在同一幀中調用多個回調。
我通過以下測試確認。 60 Hz 的刷新率轉換為 17 毫秒的周期。 如果是前者,則沒有 2 個時間戳彼此相差 17 毫秒以內,但事實並非如此。
let sleep = ms => new Promise(resolve => setTimeout(resolve, ms)); let update = async timestamp => { console.log('update called', timestamp) await sleep(10); requestAnimationFrame(update); } requestAnimationFrame(update); requestAnimationFrame(update); requestAnimationFrame(update); requestAnimationFrame(update); requestAnimationFrame(update); requestAnimationFrame(update); requestAnimationFrame(update); requestAnimationFrame(update); requestAnimationFrame(update); requestAnimationFrame(update); requestAnimationFrame(update); requestAnimationFrame(update); requestAnimationFrame(update); requestAnimationFrame(update); requestAnimationFrame(update);
您應該只使用一個requestAnimationFrame
調用作為對requestAnimationFrame
調用堆棧。 因此,單個回調版本的性能更高。
https://jsperf.com/single-raf-draw-calls-vs-multiple-raf-draw-calls
我查看了性能比較(你也應該看看)。 歡迎你不同意。 這些是在畫布元素上繪制基元。
function timeStamp() {
return window.performance && window.performance.now ? window.performance.now() : new Date().getTime();
}
function frame() {
drawCircle();
drawLines();
drawRect();
}
function render() {
if (timeStamp() >= (time || timeStamp())) {
time = timeStamp() + delayDraw;
frame();
}
requestAnimationFrame(render);
}
function render1() {
if (timeStamp() >= (time || timeStamp())) {
time = timeStamp() + delayDraw;
drawCircle();
}
requestAnimationFrame(render1);
}
function render2() {
if (timeStamp() >= (time || timeStamp())) {
time = timeStamp() + delayDraw;
drawRect();
}
requestAnimationFrame(render2);
}
function render3() {
if (timeStamp() >= (time || timeStamp())) {
time = timeStamp() + delayDraw;
drawLines();
}
requestAnimationFrame(render3);
}
我認為這段代碼實際上是對 7 次時間戳()調用和 2 次時間戳()調用進行基准測試。 看看 Chrome 46 和 47 的區別。
我認為這優化得很好,沒有任何區別。 這只是在此時測量噪聲。
我的結論是這不需要針對我的應用程序進行手動優化。
如果您擔心性能,請查看 Chrome 59 (1.8m ops/sec) 與 Chrome 71 (506k ops/sec) 之間的差異。
requestAnimationFrame 綁定一個函數調用並返回 frameID。 請求多個幀與向事件添加多個事件偵聽器不同 - 您的每個函數都在另一個幀中調用。 因此,如果您連續(每個函數遞歸地調用自身)請求幾幀,您就會失去所有更新都在一幀內呈現的好處。 所以即使有高幀率動畫也可能看起來不那么流暢。
但是:您只能對所有方法使用 cancelAnimationFrame(frameID) 並且可能需要一些額外的代碼來取消單個動畫
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.