亚洲乱码中文字幕综合,中国熟女仑乱hd,亚洲精品乱拍国产一区二区三区,一本大道卡一卡二卡三乱码全集资源,又粗又黄又硬又爽的免费视频

requestAnimationFrame用法優(yōu)化源碼解析

 更新時間:2023年10月24日 09:04:45   作者:千年老妖  
這篇文章主要介紹了requestAnimationFrame用法優(yōu)化源碼解讀,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進步,早日升職加薪

介紹

什么是requestAnimationFrame

requestAnimationFrame是瀏覽器用于定時循環(huán)操作的一個API,通常用于動畫和游戲開發(fā)。它會把每一幀中的所有DOM操作集中起來,在重繪之前一次性更新,并且關(guān)聯(lián)到瀏覽器的重繪操作。

為什么使用requestAnimationFrame而不是setTimeout或setInterval

setTimeoutsetInterval相比,requestAnimationFrame具有以下優(yōu)勢:

  • 通過系統(tǒng)時間間隔來調(diào)用回調(diào)函數(shù),無需擔心系統(tǒng)負載和阻塞問題,系統(tǒng)會自動調(diào)整回調(diào)頻率。
  • 由瀏覽器內(nèi)部進行調(diào)度和優(yōu)化,性能更高,消耗的CPU和GPU資源更少。
  • 避免幀丟失現(xiàn)象,確?;卣{(diào)連續(xù)執(zhí)行,實現(xiàn)更流暢的動畫效果。
  • 自動合并多個回調(diào),避免不必要的開銷。
  • 與瀏覽器的刷新同步,不會在瀏覽器頁面不可見時執(zhí)行回調(diào)。

requestAnimationFrame的優(yōu)勢和適用場景

requestAnimationFrame最適用于需要連續(xù)高頻執(zhí)行的動畫,如游戲開發(fā),數(shù)據(jù)可視化動畫等。它與瀏覽器刷新周期保持一致,不會因為間隔時間不均勻而導(dǎo)致動畫卡頓。

使用方法

requestAnimationFrame的基本語法

requestAnimationFrame接收一個回調(diào)函數(shù)作為參數(shù),該回調(diào)函數(shù)會在瀏覽器下一次重繪前執(zhí)行。

const animation = () => {
  // 執(zhí)行動畫
  requestAnimationFrame(animation); 
}
requestAnimationFrame(animation);

上面代碼會不停調(diào)用requestAnimationFrame,在每次瀏覽器重繪前執(zhí)行回調(diào)函數(shù),實現(xiàn)連續(xù)動畫效果。

如何在動畫中使用requestAnimationFrame

可以在回調(diào)函數(shù)里更新動畫的狀態(tài),然后清除上一幀,繪制新狀態(tài)的這一幀:

let angle = 0; 
const render = () => {
  ctx.clearRect(0, 0, width, height); // 清除上一幀
  // 更新狀態(tài)
  angle += delta;
  ctx.beginPath();
  ctx.arc(x, y, radius, 0, angle); 
  ctx.stroke();
  requestAnimationFrame(render);
}

這樣通過在每次回調(diào)中更新參數(shù),就可以實現(xiàn)對象的連續(xù)動畫了。

requestAnimationFrame的回調(diào)函數(shù)參數(shù)

requestAnimationFrame的回調(diào)函數(shù)會收到一個參數(shù),這個參數(shù)是一個時間戳,單位為毫秒,代表requestAnimationFrame被觸發(fā)的時間。可以根據(jù)這個時間戳計算兩幀的時間間隔,來調(diào)整動畫速度。

let prevTimestamp;
const render = timestamp => {
  if (!prevTimestamp) prevTimestamp = timestamp;
  const delta = timestamp - prevTimestamp;
  // 根據(jù)時間間隔計算速度
  x += speed * delta;
  prevTimestamp = timestamp;
  requestAnimationFrame(render);
}

性能優(yōu)化

避免在requestAnimationFrame回調(diào)函數(shù)中進行大量計算

由于requestAnimationFrame的回調(diào)會在一個高優(yōu)先級的線程中被同步執(zhí)行,如果回調(diào)函數(shù)中有大量計算,會導(dǎo)致此線程被阻塞,從而引起頁面卡頓。

也就是如果 requestAnimationFrame 的回調(diào)函數(shù)執(zhí)行時間超過一幀(通常是 16.67 毫秒,因為瀏覽器通常以每秒約 60 幀的速度刷新),則可能會導(dǎo)致動畫性能下降,可能出現(xiàn)掉幀的情況,最終影響用戶體驗。這是因為瀏覽器每幀的時間是有限的,如果回調(diào)函數(shù)執(zhí)行時間過長,就會導(dǎo)致下一幀的準備和繪制時間受到壓縮,導(dǎo)致動畫卡頓。

通常,應(yīng)該盡量避免在 requestAnimationFrame 的回調(diào)函數(shù)中執(zhí)行耗時的操作。為了解決這個問題,可以采取以下一些策略:

  • 優(yōu)化回調(diào)函數(shù): 使回調(diào)函數(shù)盡可能簡短,避免不必要的計算或循環(huán)。在回調(diào)中只執(zhí)行與動畫相關(guān)的必要操作。
  • 分幀處理: 如果動畫需要處理大量數(shù)據(jù)或計算復(fù)雜的操作,可以將這些操作分散到多個 requestAnimationFrame 回調(diào)中,以避免長時間的占用。
  • Web Workers: 將耗時的計算放在獨立的 Web Worker 線程中執(zhí)行,以不影響主線程和動畫渲染。
  • 幀率控制: 如果回調(diào)函數(shù)耗時較長,可以根據(jù)回調(diào)函數(shù)的實際執(zhí)行時間來控制動畫的幀率。減小動畫對象的速度或者減少渲染質(zhì)量,以適應(yīng)當前性能。
  • 監(jiān)測性能: 使用瀏覽器開發(fā)者工具來監(jiān)測性能,以找出哪些操作導(dǎo)致了回調(diào)函數(shù)執(zhí)行時間過長。

總之,確保 requestAnimationFrame 回調(diào)函數(shù)的執(zhí)行時間盡量短,以確保動畫的流暢性和性能。

使用硬件加速優(yōu)化動畫性能

啟用GPU加速渲染,可以顯著提升動畫性能。

.animated {
  transform: translateZ(0); /* 開啟硬件加速 */  
}

如何在不同設(shè)備上實現(xiàn)平滑的動畫效果

可根據(jù)requestAnimationFrame回調(diào)的時間戳,計算這一幀與上一幀的間隔時間delta,并根據(jù)delta的值采取不同的優(yōu)化手段:

  • delta特別小,說明這一幀花費時間過長,可能導(dǎo)致掉幀,可以降低動畫對象的移動速度或圖像質(zhì)量
  • delta逐漸變大,說明動畫逐漸卡頓,可以降低動畫對象數(shù)量或復(fù)雜度
  • delta波動較大,說明系統(tǒng)資源不足,可以采用簡單的動畫作為降級策略

與其他動畫庫的比較

requestAnimationFrame與setTimeout/setInterval的區(qū)別

  • setTimeout/setInterval是固定時間間隔觸發(fā), requestAnimationFrame依賴系統(tǒng)刷新調(diào)度
  • setTimeout/setInterval會無視頁面是否可見, requestAnimationFrame會停止刷新
  • setTimeout/setInterval難以避免丟幀問題,requestAnimationFrame與刷新同步避免丟幀

requestAnimationFrame與CSS動畫的結(jié)合使用

requestAnimationFrame可用于更新動畫狀態(tài),實現(xiàn)復(fù)雜動畫邏輯,而CSS動畫用于聲明式定義動畫的樣式變化,兩者可配合實現(xiàn)更豐富的動畫效果。

實際應(yīng)用

使用requestAnimationFrame實現(xiàn)常見動畫效果

可使用 requestAnimationFrame 實現(xiàn)對象軌跡動畫、SVG圖形動畫、加載動畫等效果。

// 小球拖尾效果
const positions = [];
const render = () => {
  // 添加新位置
  positions.push({x, y});
  if (positions.length > 10){
    positions.shift(); 
  }
  // 渲染小球
  ctx.clearRect(0, 0, width, height);
  positions.forEach(pos => ctx.fillRect(pos.x, pos.y, 10, 10));
  requestAnimationFrame(render);
}
// SVG繪制動畫
let length = 0;
const render = () => {
  length += 4;
  svgLine.setAttribute("stroke-dasharray", length);
  if (length < 300) {
    requestAnimationFrame(render);
  }
}
requestAnimationFrame(render); 
// 進度條加載動畫  
let progress = 0;
const render = () => {
  progress += 1; 
  loadBar.style.width = progress + '%';
  if(progress < 100) {
    requestAnimationFrame(render);
  }
}
requestAnimationFrame(render);

requestAnimationFrame在游戲開發(fā)中的應(yīng)用

游戲需要非常流暢的畫面和實時的響應(yīng),這正是requestAnimationFrame的優(yōu)勢,它可用于實現(xiàn)游戲中的物體移動、碰撞檢測、幀數(shù)控制等操作。

// 飛機射擊動畫
const update = () => {
  // 子彈位置更新
  bullets.forEach(bullet => {
    bullet.position += speed;
  })
  // 飛機位置更新
  aircraft.position += delta * speed;
  // 繪制所有元素
  render(bullets, aircraft);
  requestAnimationFrame(update);
}

requestAnimationFrame在響應(yīng)式設(shè)計中的應(yīng)用

可使用requestAnimationFrame來更平滑地執(zhí)行響應(yīng)式布局的變化,避免布局突然大幅移動帶來的視覺沖擊感。

let width = 500;
const resize = () => {
  width = container.clientWidth;
  box.style.width = width + "px";
  requestAnimationFrame(resize);
}
window.addEventListener("resize", resize);

兼容性和后續(xù)發(fā)展

requestAnimationFrame的瀏覽器兼容性

requestAnimationFrame現(xiàn)在已經(jīng)得到了廣泛支持,可以直接使用。對于不支持的瀏覽器,可以用setTimeout模擬requestAnimationFrame

window.requestAnimationFrame = window.requestAnimationFrame ||
                               window.webkitRequestAnimationFrame ||
                               (cb => setTimeout(cb, 1000/60));

requestAnimationFrame的未來發(fā)展趨勢

未來requestAnimationFrame可能會支持設(shè)置幀率、增強調(diào)度算法等,提升動畫性能。Web工作者線程也可帶來更多優(yōu)化空間。

瀏覽器廠商也在繼續(xù)改進相關(guān)API,比如setTimeoutrequestIdleCallback也在朝著更精確的調(diào)度方向發(fā)展。

如何在不支持requestAnimationFrame的瀏覽器中實現(xiàn)類似效果

可以通過自己實現(xiàn)一個polyfill:

window.requestAnimationFrame = window.requestAnimationFrame || 
                               window.webkitRequestAnimationFrame ||
                               (cb => setTimeout(cb, 1000/60));

這樣就可以在大多數(shù)瀏覽器中使用 requestAnimationFrame 了。對于老舊瀏覽器,可以使用 setInterval 模擬,但效果會比較粗糙。

總結(jié)

requestAnimationFrame是實現(xiàn)復(fù)雜動畫的好幫手,必須掌握其用法與優(yōu)化技巧,才能發(fā)揮其最大效用。同時結(jié)合其他技術(shù)如CSS動畫、Web Worker等也可以實現(xiàn)更好的性能。隨著瀏覽器的不斷進步,requestAnimationFrame還具有很大的拓展?jié)摿Α?/p>

以上就是requestAnimationFrame用法優(yōu)化源碼解析的詳細內(nèi)容,更多關(guān)于requestAnimationFrame優(yōu)化的資料請關(guān)注腳本之家其它相關(guān)文章!

相關(guān)文章

最新評論