版權(quán)說(shuō)明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請(qǐng)進(jìn)行舉報(bào)或認(rèn)領(lǐng)
文檔簡(jiǎn)介
第關(guān)于JavaScript實(shí)現(xiàn)動(dòng)畫時(shí)動(dòng)畫抖動(dòng)的原因與解決方法目錄使用定時(shí)器實(shí)現(xiàn)動(dòng)畫出現(xiàn)卡頓的原因requestAnimationFrame的前世今生requestAnimationFrameVSsetInterval參考資料總結(jié)前段時(shí)間在使用JavaScript做動(dòng)畫的時(shí)候發(fā)現(xiàn)做出來(lái)的動(dòng)畫會(huì)出現(xiàn)卡頓的現(xiàn)象,今天我們主要就來(lái)聊一下卡頓的原因以及如何解決這個(gè)問(wèn)題。
使用定時(shí)器實(shí)現(xiàn)動(dòng)畫出現(xiàn)卡頓的原因
主要原因是瀏覽器無(wú)法確定定時(shí)器的回調(diào)函數(shù)的執(zhí)行時(shí)機(jī)。以setInterval為例,當(dāng)一個(gè)setInterval定時(shí)器被創(chuàng)建后,它的回調(diào)任務(wù)會(huì)被放到異步隊(duì)列,只有當(dāng)同步任務(wù)執(zhí)行完成后,瀏覽器才會(huì)檢查異步隊(duì)列中是否有需要執(zhí)行的異步任務(wù),如果有,就取出執(zhí)行,這樣會(huì)使任務(wù)的實(shí)際執(zhí)行時(shí)機(jī)比所設(shè)定的延遲時(shí)間要晚一些。
這個(gè)問(wèn)題跟瀏覽器的事件循環(huán)機(jī)制有關(guān),JavaScript引擎在解析執(zhí)行我們的代碼的時(shí)候,遇到定時(shí)器,會(huì)調(diào)用瀏覽器API,讓定時(shí)器去進(jìn)行倒計(jì)時(shí),此時(shí)并不阻塞同步代碼的執(zhí)行,當(dāng)定時(shí)器倒計(jì)時(shí)完畢,定時(shí)器回調(diào)會(huì)被放入宏任務(wù)隊(duì)列等待執(zhí)行。
在這個(gè)過(guò)程中問(wèn)題就來(lái)了,如果說(shuō)同步代碼的執(zhí)行需要50ms,而定時(shí)器設(shè)置的定時(shí)只有20ms,那么由于事件循環(huán)的機(jī)制,還是要等待同步任務(wù)執(zhí)行完整之后再來(lái)執(zhí)行微任務(wù)隊(duì)列中的定時(shí)器回調(diào),而這中間,又相隔了30ms,在這30ms的過(guò)程中,定時(shí)器的回調(diào)一直處于pendding的狀態(tài)。如果定時(shí)器中是動(dòng)畫相關(guān)的操作,那也需要在預(yù)期的時(shí)間上多等待50ms。
畫了張圖,希望能幫助大家理解(如果不能幫助大家理解,那么請(qǐng)忽略這張圖)
屏幕分辨率和尺寸也會(huì)影響刷新頻率,不同設(shè)備的屏幕繪制頻率可能會(huì)有所不同,而setInterval只能設(shè)置一個(gè)固定的時(shí)間間隔,這個(gè)間隔時(shí)間不一定與屏幕的刷新時(shí)間同步,所以就可能會(huì)導(dǎo)致動(dòng)畫出現(xiàn)隨機(jī)丟幀的問(wèn)題。
這里有兩個(gè)點(diǎn),一個(gè)是顯示器的刷新頻率,另一個(gè)是定時(shí)器的時(shí)間間隔。
一般顯示器刷新頻率都是60Hz,這基本上意味著每秒需要重繪60次。大多數(shù)瀏覽器都會(huì)限制重繪的頻率,使其不超過(guò)顯示器的刷新頻率。因?yàn)槌^(guò)刷新頻率,用戶也感知不到,白白浪費(fèi)性能。
因此,實(shí)現(xiàn)平滑動(dòng)畫最佳的重繪間隔為1000ms/60,大約17毫秒。以這個(gè)速度重繪,可以實(shí)現(xiàn)最平滑的動(dòng)畫效果。因?yàn)檫@已經(jīng)是瀏覽器的重繪頻率的極限了。
知道何時(shí)繪制下一幀,是創(chuàng)造平滑動(dòng)畫的關(guān)鍵。直到幾年前,都沒(méi)有確切保證讓瀏覽器在何時(shí)把下一幀繪制出來(lái)的方法。隨著canvas和HTML5游戲的興起,開(kāi)發(fā)者發(fā)現(xiàn)setInterval和setTimeout的不精確是個(gè)大問(wèn)題,而瀏覽器自身的計(jì)時(shí)器也存在著精度不足毫秒的問(wèn)題。
以下是幾個(gè)瀏覽器計(jì)時(shí)器的精度情況:
IE8以及之前的版本計(jì)時(shí)器精度為15.625ms;IE9及之后的版計(jì)時(shí)器精度為4ms;FireFox和Safari的計(jì)時(shí)器精度約為10ms;Chrome的計(jì)時(shí)器精度為4ms。
以Chrome為例,它的計(jì)時(shí)器精度為4ms,這意味著0~4之間的任何值最終要么是0,要么是4;不可能是別的值。因此,即使將瀏覽器的時(shí)間間隔設(shè)置為最優(yōu),也免不了只能得到相近似的結(jié)果。
對(duì)于JavaScript來(lái)說(shuō),它不知道瀏覽器會(huì)在何時(shí)發(fā)生重繪。因此,我們通過(guò)定時(shí)器做動(dòng)畫的時(shí)候,在定時(shí)器中控制動(dòng)畫的代碼已經(jīng)執(zhí)行完成的情況下,動(dòng)畫效果并不一定會(huì)立馬生效,因?yàn)榇藭r(shí)瀏覽器可能還處在等待下一次重繪的過(guò)程中,當(dāng)下一次重繪完成,動(dòng)畫效果才能在瀏覽器窗口中顯示出來(lái)。
而由于瀏覽器計(jì)時(shí)器時(shí)間差的問(wèn)題,會(huì)導(dǎo)致定時(shí)器的計(jì)時(shí)并不一定是我們?cè)O(shè)置的17ms,而是在多個(gè)時(shí)間點(diǎn)內(nèi)反復(fù)橫跳,也因此才出現(xiàn)使用定時(shí)器做動(dòng)畫的時(shí)候動(dòng)畫抖動(dòng)的問(wèn)題,在復(fù)雜的動(dòng)畫中,這種問(wèn)題尤為明顯。
在這樣的環(huán)境下,今天的主角requestAnimationFrame應(yīng)運(yùn)而生!
requestAnimationFrame的前世今生
Mozilla的RobertOCallahan一直在思考這個(gè)問(wèn)題,并且提出了一個(gè)獨(dú)特的解決方案。他指出,瀏覽器知道CSS過(guò)渡和動(dòng)畫應(yīng)該什么時(shí)候開(kāi)始,并且能夠計(jì)算出正確的時(shí)間間隔,到時(shí)間就去刷新用戶界面。
但是對(duì)于JavaScript而言,瀏覽器并不知道動(dòng)畫什么時(shí)候開(kāi)始。他給出的方案是創(chuàng)造一個(gè)名為MozRequestAnimationFrame的新方法,以此來(lái)通知瀏覽器某些JavaScript代碼要執(zhí)行動(dòng)畫了。這樣瀏覽器就可以在運(yùn)行某些代碼后進(jìn)行適當(dāng)?shù)膬?yōu)化。
目前,所有的瀏覽器都支持這個(gè)方法不帶前綴的版本,也就是現(xiàn)在用到的requestAnimationFrame。
requestAnimationFrameVSsetInterval
這里就不再過(guò)多的介紹requestAnimationFrame的詳細(xì)用法了,它的用法并不復(fù)雜。
與定時(shí)器不同的是,requestAnimationFrame只會(huì)在被調(diào)用的時(shí)候執(zhí)行一次動(dòng)畫,而不會(huì)連續(xù)執(zhí)行。如果想做連續(xù)的動(dòng)畫,則可以通過(guò)遞歸來(lái)實(shí)現(xiàn)對(duì)requestAnimationFrame的連續(xù)調(diào)用。
接下來(lái)通過(guò)一個(gè)demo來(lái)對(duì)比一下使用requestAnimationFrame和setInterval兩者做出來(lái)的動(dòng)畫效果之間的差異。
!DOCTYPEhtml
htmllang="en"
head
metacharset="UTF-8"/
metahttp-equiv="X-UA-Compatible"content="IE=edge"/
metaname="viewport"content="width=device-width,initial-scale=1.0"/
titleDocument/title
/head
style
.square1,
.square2{
position:absolute;
width:100px;
height:100px;
.square1{
top:40px;
background:red;
.square2{
top:150px;
background:blue;
/style
body
div
div/div
div/div
button開(kāi)始!/button
/div
script
constsquare1El=document.querySelector('.square1')
constsquare2El=document.querySelector('.square2')
//定時(shí)器版
functionsquareMove(){
lettimer=null
square1El.style.left='0px'
timer=setInterval(()={
constsquareLeft=parseInt(square1El.style.left)
if(squareLeft=500)returnclearInterval(timer)
square1El.style.left=squareLeft+1+'px'
},17)
//requestAnimationFrame版
functionsquareMove2(){
lettimer=null
square2El.style.left='0px'
functionupdateAnimation(){
constsquareLeft=parseInt(square2El.style.left)
if(squareLeft=500)returncancelAnimationFrame(timer)
square2El.style.left=squareLeft+1+'px'
window.requestAnimationFrame(updateAnimation)
window.requestAnimationFrame(updateAnimation)
document.querySelector('.btn').addEventListener('click',()={
squareMove()
squareMove2()
/script
/body
/html
在頁(yè)面中畫了兩個(gè)正方形,當(dāng)點(diǎn)擊按鈕的時(shí)候方塊開(kāi)始運(yùn)動(dòng),紅色方塊是使用setInterval實(shí)現(xiàn)的動(dòng)畫,藍(lán)色方塊使用的是requestAnimationFrame。
接下來(lái)看一下實(shí)現(xiàn)的效果。
在生成gif的時(shí)候視頻被壓縮了,但是還是能看到紅色的方塊在開(kāi)始運(yùn)動(dòng)的時(shí)候有明顯的抖動(dòng),而藍(lán)色的方塊則比較絲滑。
實(shí)際上,requestAnimationFrame的回調(diào)函數(shù)可以接收一個(gè)參數(shù),這個(gè)參數(shù)是一個(gè)DOMHightResTimeStamp的實(shí)例(比如:performance.now()的返回值),用來(lái)表示下一次重繪的時(shí)間。這一點(diǎn)非常重要,requestAnimationFrame實(shí)際上是把重繪任務(wù)安排在了未來(lái)的一個(gè)已知的時(shí)間點(diǎn)上,而且通過(guò)這個(gè)參數(shù)來(lái)告訴開(kāi)發(fā)者。
類似于setInterval的清除方法clearInterval,requestAnimationFrame也有對(duì)應(yīng)的取消重繪的方法cancelAnimationFrame,用法也跟clearInterval非常類似,在每次調(diào)用requestAnimationFrame的時(shí)候,都會(huì)返回一個(gè)id,cancelAnimationFra
溫馨提示
- 1. 本站所有資源如無(wú)特殊說(shuō)明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請(qǐng)下載最新的WinRAR軟件解壓。
- 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請(qǐng)聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶所有。
- 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁(yè)內(nèi)容里面會(huì)有圖紙預(yù)覽,若沒(méi)有圖紙預(yù)覽就沒(méi)有圖紙。
- 4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
- 5. 人人文庫(kù)網(wǎng)僅提供信息存儲(chǔ)空間,僅對(duì)用戶上傳內(nèi)容的表現(xiàn)方式做保護(hù)處理,對(duì)用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對(duì)任何下載內(nèi)容負(fù)責(zé)。
- 6. 下載文件中如有侵權(quán)或不適當(dāng)內(nèi)容,請(qǐng)與我們聯(lián)系,我們立即糾正。
- 7. 本站不保證下載資源的準(zhǔn)確性、安全性和完整性, 同時(shí)也不承擔(dān)用戶因使用這些下載資源對(duì)自己和他人造成任何形式的傷害或損失。
最新文檔
- 執(zhí)業(yè)獸醫(yī)考試考試題預(yù)防科目及答案
- 煙花爆竹考試題及答案
- 監(jiān)護(hù)人防溺水測(cè)試題附答案
- 幼兒教育題庫(kù)論述題及答案
- 二建網(wǎng)絡(luò)考試題及答案
- 新安全生產(chǎn)法試題庫(kù)及參考答案
- 中藥試題+答案
- 重癥醫(yī)學(xué)科考試試題與答案
- 陜西省延安市輔警公共基礎(chǔ)知識(shí)題庫(kù)(附答案)
- 客服營(yíng)銷面試試題及答案
- 2026中國(guó)電信四川公用信息產(chǎn)業(yè)有限責(zé)任公司社會(huì)成熟人才招聘?jìng)淇碱}庫(kù)及參考答案詳解1套
- 2025年廣東省生態(tài)環(huán)境廳下屬事業(yè)單位考試真題附答案
- 2026年安徽省公務(wù)員考試招錄7195名備考題庫(kù)完整參考答案詳解
- 【地理】期末模擬測(cè)試卷-2025-2026學(xué)年七年級(jí)地理上學(xué)期(人教版2024)
- LoRa技術(shù)教學(xué)課件
- GB/T 1957-2006光滑極限量規(guī)技術(shù)條件
- GB 28480-2012飾品有害元素限量的規(guī)定
- 劉一秒演說(shuō)智慧經(jīng)典(內(nèi)部筆記)
- 管道TOFD檢測(cè)記錄及續(xù)表
- 馬克思主義哲學(xué)精講課件
- 期末考試總安排
評(píng)論
0/150
提交評(píng)論