动画函数requestAnimationFrame
經典動畫
話不多說,首先來個經典的動畫函數:
function animate(element, name, from, to, time) { time = time || 800; //默認0.8秒 var style = element.style, latency = 60, // 每60ms一次變化 count = time / latency, //變化的次數 step = Math.round((to - from) / count), //每一步的變化量 now = from; function go() { count--; now = count ? now + step : to; style[name] = now + 'px'; if (count) { setTimeout(go, latency); } } style[name] = from + 'px'; setTimeout(go, latency); }姑且不論這個函數的設計存在局限性,如只能對以px為單位的樣式進行修改。僅從函數的實現上來看,這可以是一個非常經典的動畫理念,其基本邏輯由以下部分組成:
這個函數工作得很好,服務了千千萬萬的站點和系統,事實上jQuery的animate函數的核心也無非是setInterval函數。
但是,隨著現在系統復雜度的穩步上升,動畫效果也越來越多,同時對動畫的流暢度也有了更多的重視,這導致上面的函數會出現一些問題。例如同時打開 100個動畫效果,根據上面的函數,很明顯會有100個定時器在同時運行,這些定時器之間的調度會對性能有輕微的影響。雖然在正常的環境中,這些許的影響 并不會有什么關系,但是在動畫這種對流暢度有很高要求的環境下,任何細微的影響都可能產生出不好的用戶體驗。
在這樣的情況下,有一些開發者就發明了一種基于統一幀管理的動畫框架,他使用一個定時器觸發動畫幀,不同的動畫來注冊這些幀,在每一幀上處理多個動 畫的屬性變化。這樣的好處是減少了定時器調度的開銷,但是對于動畫框架的開發者來說,統一幀管理、提供監聽幀的API等,都是需要開發和維護的。
瀏覽器的直接支持
最終,瀏覽器廠商們發現這件事其實可以由他們來做,并且基于瀏覽器層面,還可以有更多的優化,比如:
- 對于一個偵中對DOM的所有操作,只進行一次Layout和Paint。
- 如果發生動畫的元素被隱藏了,那么就不再去Paint。
于是,瀏覽器開始推出一個API,叫做requestAnimationFrame,關于這個函數,MDC的相關頁面有比較詳細的介紹,簡單來說,這個函數有2種使用方法:
第2種方法由于依賴于Firefox自己的事件,且beforepaint事件還沒進入到標準中,所以不推薦使用,還是使用第1種方式比較好。此時,我們的動畫邏輯可以變成這樣:
新的動畫函數
下面就是一個全新的動畫函數:
function animate(element, name, from, to, time) { time = time || 800; // 默認0.8秒 var style = element.style, startTime = new Date; function go(timestamp) { var progress = timestamp - startTime; if (progress >= duration) { style[name] = to + 'px'; return; } var now = (to - from) * (progress / duration); style[name] = now.toFixed() + 'px'; requestAnimationFrame(go); } style[name] = from + 'px'; requestAnimationFrame(go); }到這一步,還剩一個問題,那就是并不是每個瀏覽器都支持requestAnimationFrame函數的,所以再做一個簡單的修正。
根據Firefox的特性來看,其mozRequestAnimationFrame提供的最高FPS為60,并且會根據每一幀的計算的耗時來進行調整,比如每一幀計算用了1s,那他只會提供1FPS的動畫效果。
而Chrome的高版本同樣也實現了這個函數,叫webkitRequestAnimationFrame,可以預見未來還會有Opera的oRequestAnimationFrame和IE的msRequestAnimationFrame,所以這里一并做一個簡單的兼容處理:
requestAnimationFrame = window.requestAnimationFrame || window.mozRequestAnimationFrame || window.webkitRequestAnimationFrame || window.msRequestAnimationFrame || window.oRequestAnimationFrame || function(callback) { setTimeout(callback, 1000 / 60); };轉載于:https://blog.51cto.com/kuiba/830814
總結
以上是生活随笔為你收集整理的动画函数requestAnimationFrame的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: YUV422转RGB24
- 下一篇: SQL Server 系统存储过程