爲什麼 Canvas 內元素動畫老是在顫抖?

來源: https://fanmingfei.com/posts/...

背景

過年的項目中遇到一個問題讓我百思不得其解,明明個人幀率保持在60幀,爲什麼個人動畫卻一直抖動?html

個人場景是一個勻速直線運動的小姐姐。前端

先上一個 Demopost

在這個 Demo 中,小姐姐是按照 x 軸 10px/s,y 軸 30 px/s 進行移動的,不過她的移動是明顯伴隨着抖動的。動畫

這究竟是怎麼了呢?code

解決

若是小姐姐的y軸速度是 10px/s,咱們的幀率是 60f/s,計算一下:htm

10 / 60 = 1/6 (px/f)

實際上,的實際速度是每 6 幀纔會移動 1px,這固然會有抖動,小姐姐走一步停一會,總感受怪怪的~遊戲

我索性把小姐姐的移動速度調快,調成 100px/s,發現,仍是會抖動,覺得高高興興能解決了這個問題,發現仍是沒那麼簡單。遊戲開發

既然咱們能算,那咱們就算一算開發

100 / 60 = 10/6 (px/f) = 1.666666....(px/f)

寫了個for循環,看看一秒中每一幀小姐姐都在什麼位置get

for(let i = 0; i < 60; i ++) {
  console.log(i*10/6)
}

輸出結果取小數點後兩位是這樣的:

0.00 1.67 3.33 5.00 6.67 8.33 10.00 11.67 13.33 15.00 16.67 18.33 20.00 21.67 23.33 25.00 26.67 28.33 30.00 31.67
33.33 35.00 36.67 38.33 40.00 41.67 43.33 45.00 46.67 48.33 50.00 51.67 53.33 55.00 56.67 58.33 60.00 61.67 63.33
65.00 66.67 68.33 70.00 71.67 73.33 75.00 76.67 78.33 80.00 81.67 83.33 85.00 86.67 88.33 90.00 91.67 93.33 95.00 96.67 98.33

那麼做爲浮點數,Canvas 將如何定位呢?

咱們來寫一個 Demo

使用 Chrome 打開,做爲一個像素眼,我發現,小姐姐定位在 50.6px 的時候,其實就已經被渲染到 51px 的位置。

因此在 Chrome 中,drawImage 中設置的位置最終會被四捨五入,這可能和 CSS Sub-pixel 有關 這裏先不探究。

因此真正的位置實際上是

0 2 3 5 7 8 10 12 13 15 17 18 20 22 23 25 27 28 30 32
 33 35 37 38 40 42 43 45 47 48 50 52 53 55 57 58 60 62 63 65
 67 68 70 72 73 75 77 78 80 82 83 85 87 88 90 92 93 95 97 98

從數值來看,每幀移動的距離多是 1px 也多是 2px,小姐姐多是在邊跳芭蕾邊走路嘍~

既然這樣,60 幀的幀率下,設置 60px/s 就能夠解決問題了,嘗試了一下,真的能夠!

總結

前端動畫/遊戲開發 requestAnimationFrame 之 鎖幀 這篇文章介紹過,在項目中咱們可能對動畫進行鎖幀,幀率多是 60 或者 30,若是咱們想保證渲染不抖動,在勻速直線運動中,咱們儘可能保證咱們設置的速度要是幀率的倍數,或者保證平均每幀移動的像素點是同樣的。

drawImage 中,不建議使用浮點數進行定位。

相關文章
相關標籤/搜索