日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

动画函数requestAnimationFrame

發(fā)布時(shí)間:2024/4/14 编程问答 31 豆豆
生活随笔 收集整理的這篇文章主要介紹了 动画函数requestAnimationFrame 小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

經(jīng)典動畫

話不多說,首先來個(gè)經(jīng)典的動畫函數(shù):

function animate(element, name, from, to, time) { time = time || 800; //默認(rèn)0.8秒 var style = element.style, latency = 60, // 每60ms一次變化 count = time / latency, //變化的次數(shù) 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); }

姑且不論這個(gè)函數(shù)的設(shè)計(jì)存在局限性,如只能對以px為單位的樣式進(jìn)行修改。僅從函數(shù)的實(shí)現(xiàn)上來看,這可以是一個(gè)非常經(jīng)典的動畫理念,其基本邏輯由以下部分組成:

  • 獲取起點(diǎn)值from和終點(diǎn)值to,通過動畫需要進(jìn)行的時(shí)間time,以及每偵間隔latency的要求,計(jì)算出值的改變次數(shù)count和每次改變的量step。
  • 開啟setTimeout(fn, latency);來步進(jìn)到下一偵。
  • 在下一偵中,設(shè)置屬性步進(jìn)一次,如果動畫還沒結(jié)束,再回到第2步繼續(xù)下一偵。
  • 這個(gè)函數(shù)工作得很好,服務(wù)了千千萬萬的站點(diǎn)和系統(tǒng),事實(shí)上jQuery的animate函數(shù)的核心也無非是setInterval函數(shù)。

    但是,隨著現(xiàn)在系統(tǒng)復(fù)雜度的穩(wěn)步上升,動畫效果也越來越多,同時(shí)對動畫的流暢度也有了更多的重視,這導(dǎo)致上面的函數(shù)會出現(xiàn)一些問題。例如同時(shí)打開 100個(gè)動畫效果,根據(jù)上面的函數(shù),很明顯會有100個(gè)定時(shí)器在同時(shí)運(yùn)行,這些定時(shí)器之間的調(diào)度會對性能有輕微的影響。雖然在正常的環(huán)境中,這些許的影響 并不會有什么關(guān)系,但是在動畫這種對流暢度有很高要求的環(huán)境下,任何細(xì)微的影響都可能產(chǎn)生出不好的用戶體驗(yàn)。

    在這樣的情況下,有一些開發(fā)者就發(fā)明了一種基于統(tǒng)一幀管理的動畫框架,他使用一個(gè)定時(shí)器觸發(fā)動畫幀,不同的動畫來注冊這些幀,在每一幀上處理多個(gè)動 畫的屬性變化。這樣的好處是減少了定時(shí)器調(diào)度的開銷,但是對于動畫框架的開發(fā)者來說,統(tǒng)一幀管理、提供監(jiān)聽幀的API等,都是需要開發(fā)和維護(hù)的。

    瀏覽器的直接支持

    最終,瀏覽器廠商們發(fā)現(xiàn)這件事其實(shí)可以由他們來做,并且基于瀏覽器層面,還可以有更多的優(yōu)化,比如:

    • 對于一個(gè)偵中對DOM的所有操作,只進(jìn)行一次Layout和Paint。
    • 如果發(fā)生動畫的元素被隱藏了,那么就不再去Paint。

    于是,瀏覽器開始推出一個(gè)API,叫做requestAnimationFrame,關(guān)于這個(gè)函數(shù),MDC的相關(guān)頁面有比較詳細(xì)的介紹,簡單來說,這個(gè)函數(shù)有2種使用方法:

  • 調(diào)用requestAnimationFrame函數(shù),傳遞一個(gè)callback參數(shù),則在下一個(gè)動畫幀時(shí),會調(diào)用callback。
  • 不傳遞參數(shù)地直接調(diào)用該函數(shù),啟動動畫幀,下一個(gè)幀觸發(fā)時(shí),會同時(shí)觸發(fā)window.onmozbeforepaint事件,可以通過注冊該事件來進(jìn)行動畫。
  • 第2種方法由于依賴于Firefox自己的事件,且beforepaint事件還沒進(jìn)入到標(biāo)準(zhǔn)中,所以不推薦使用,還是使用第1種方式比較好。此時(shí),我們的動畫邏輯可以變成這樣:

  • 記錄當(dāng)前時(shí)間startTime,作為動畫開始的時(shí)間。
  • 請求下一幀,帶上回調(diào)函數(shù)。
  • 下一幀觸發(fā)時(shí),回調(diào)函數(shù)的第一個(gè)參數(shù)為當(dāng)前的時(shí)間,再與startTime進(jìn)行比較,確定時(shí)間間隔ellapseTime。
  • 判斷ellapseTime是否已經(jīng)超過事先設(shè)定的動畫時(shí)間time,如果超過,則結(jié)束動畫。
  • 計(jì)算動畫屬性變化的差值differ = to - from,再確定在ellapseTime的時(shí)候應(yīng)該變化多少step = differ / time * ellapseTime。
  • 計(jì)算出現(xiàn)在應(yīng)該變化到的位置Math.round(from + step),并重新對樣式賦值。
  • 繼續(xù)請求下一幀。
  • 新的動畫函數(shù)

    下面就是一個(gè)全新的動畫函數(shù):

    function animate(element, name, from, to, time) { time = time || 800; // 默認(rèn)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); }

    到這一步,還剩一個(gè)問題,那就是并不是每個(gè)瀏覽器都支持requestAnimationFrame函數(shù)的,所以再做一個(gè)簡單的修正。

    根據(jù)Firefox的特性來看,其mozRequestAnimationFrame提供的最高FPS為60,并且會根據(jù)每一幀的計(jì)算的耗時(shí)來進(jìn)行調(diào)整,比如每一幀計(jì)算用了1s,那他只會提供1FPS的動畫效果。

    而Chrome的高版本同樣也實(shí)現(xiàn)了這個(gè)函數(shù),叫webkitRequestAnimationFrame,可以預(yù)見未來還會有Opera的oRequestAnimationFrame和IE的msRequestAnimationFrame,所以這里一并做一個(gè)簡單的兼容處理:

    requestAnimationFrame = window.requestAnimationFrame || window.mozRequestAnimationFrame || window.webkitRequestAnimationFrame || window.msRequestAnimationFrame || window.oRequestAnimationFrame || function(callback) { setTimeout(callback, 1000 / 60); };

    轉(zhuǎn)載于:https://blog.51cto.com/kuiba/830814

    總結(jié)

    以上是生活随笔為你收集整理的动画函数requestAnimationFrame的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

    如果覺得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。