前端動畫大亂燉

發表於2017-11-29

作為一隻前端狗,我們的使命就是在滿足產品需求、實現互動設計的基礎上,將最好的體驗呈現給使用者爸爸們。在保證效能的同時,我們通常會給頁面加一些動態效果,以增強頁面的表現力並提升頁面的互動體驗。故將前端實現動效的幾種常用方式整理成此篇小結,以求溫故而知新,如有不當還望多多指正2165169-d595eeccfc292e3b

童年.png

動畫即童年

動畫是指由許多幀靜止的畫面,以一定的速度(如每秒16張)連續播放時,肉眼因視覺殘象產生錯覺,而誤以為畫面活動的作品。– 維基百科

以上是維基百科上給出的動畫的定義。相信每一個像我這樣有童年的孩子,應該都玩過手翻書,或者就算你的童年稍微暗淡一點,應該也看過動畫片吧…嗯嗯,並沒有跑題,其實這和我們今天提及的動畫本質上是一樣的,只不過就是呈現方式或者說載體發生了改變。

2165169-7f16bceb975ee4ac
超人大戰賽亞人.avi

幾個基本概念

簡單介紹幾個關於動畫的基本概念:

:在動畫過程中,每一幅靜止畫面即為一“幀”;
幀率:即每秒鐘播放的靜止畫面的數量,單位是fps(Frame per second)或赫茲(Hz);
幀時長:即每一幅靜止畫面的停留時間,單位一般是ms(毫秒);
丟幀:在幀率固定的動畫中,某一幀的時長遠高於平均幀時長,導致其後續數幀被擠壓而丟失的現象;

我們在顯示器上看到的動畫,每一幀變化都是系統繪製出來的(GPU或者CPU)。它的最高繪製頻率受限於顯示器的重新整理頻率(而非顯示卡,大多數是60Hz或者75Hz)。

幀頻越高,螢幕上圖片閃爍感就越小,穩定性也就越高。人的眼睛不容易察覺75Hz以上重新整理頻率帶來的閃爍感。

實現方式

通常我們在前端實現動畫效果的幾種主要實現方式如下:

  • JavaScript:通過定時器(setTimeout 和 setIterval)來間隔來改變元素樣式,或者使用requestAnimationFrame;
  • CSS3:transition 和 animation;
  • HTML5:使用HTML5提供的繪圖方式(canvas、svg、webgl);
2165169-e4ae351a160af657
Animations.png

requestAnimationFrame

requestAnimationFrame是瀏覽器用於定時迴圈操作的一個介面,類似於setTimeout,主要用途是按幀對網頁進行重繪

設定這個API的目的是為了讓各種網頁動畫效果(DOM動畫、Canvas動畫、SVG動畫、WebGL動畫)能夠有一個統一的重新整理機制,從而節省系統資源,提高系統效能,改善視覺效果。程式碼中使用這個API,就是告訴瀏覽器希望執行一個動畫,讓瀏覽器在下一個動畫幀安排一次網頁重繪。

requestAnimationFrame使用一個回撥函式作為引數,這個回撥函式會在瀏覽器重繪之前呼叫,由於功效只是一次性的,所以想實現連續的動效,需要遞迴呼叫,示例如下:

cancelAnimationFrame方法用於取消重繪:

使用requestAnimationFrameAPI的優勢如下:

  • 會把每一幀中的所有DOM操作集中起來,在一次重繪或迴流中就完成,並且重繪或迴流的時間間隔緊緊跟隨顯示器的重新整理頻率(60 Hz或者75 Hz);
  • 在隱藏或不可見的元素中,將不會進行重繪或迴流,這當然就意味著更少的的cpu,gpu和記憶體使用量;

目前,主要瀏覽器Firefox 23 / IE 10 / Chrome / Safari)都支援這個方法。可以用下面的方法,檢查瀏覽器是否支援這個API。如果不支援,則自行模擬部署該方法。

所以,可以這麼說,requestAnimationFrame就是一個效能優化版、專為動畫量身打造的setTimeout,不同的是requestAnimationFrame不是自己指定回撥函式執行的時間,而是跟著瀏覽器內建的重新整理頻率來執行回撥,這當然就能達到瀏覽器所能實現動畫的最佳效果了。

DEMO傳送門

Transition

CSS 中的 transition 屬性允許塊級元素中的屬性在指定的時間內平滑的改變,簡單看下其語法規則:

具體屬性值介紹如下:

描述
transition-property 規定設定過渡效果的 CSS 屬性的名稱。(none / all / property)
transition-duration 規定完成過渡效果需要多少秒或毫秒。
transition-timing-function 規定速度效果的速度曲線。(linear、ease、ease-in、ease-out、ease-in-out、cubic-bezier(n,n,n,n))
transition-delay 定義過渡效果何時開始。

DEMO傳送門

Animation

類似的CSS還提供了一個Animation屬性,不過區別於Transition,Animation作用於元素本身而不是樣式屬性,可以使用關鍵幀的概念,應該說可以實現更自由的動畫效果。

語法

具體屬性值介紹如下:

描述
animation-name 規定需要繫結到選擇器的 keyframe 名稱。(keyframename、none)
animation-duration 規定完成動畫所花費的時間,以秒或毫秒計。
animation-timing-function 規定動畫的速度曲線。(linear、ease、ease-in、ease-out、ease-in-out、cubic-bezier(n,n,n,n))
animation-delay 規定在動畫開始之前的延遲。
animation-iteration-count 規定動畫應該播放的次數。
animation-direction 規定是否應該輪流反向播放動畫。 (normal、alternate)

DEMO傳送門

Canvas

是HTML5新增的元素,作為頁面圖形繪製的容器,可用於通過使用JavaScript中的指令碼來繪製圖形。例如,它可以用於繪製圖形,製作照片,建立動畫,甚至可以進行實時視訊處理或渲染,Canvas具有如下特點:

  • 依賴解析度,基於點陣圖;
  • 不支援事件處理器;
  • 弱的文字渲染能力;
  • 能夠以 .png 或 .jpg 格式儲存結果影象;
  • 最適合影象密集型的遊戲,其中的許多物件會被頻繁重繪;

大多數 Canvas 繪圖 API 都沒有定義在

DEMO傳送門

SVG

SVG是英文Scalable Vector Graphics的縮寫,意為可縮放向量圖形,用來定義用於網路的基於向量的圖形,其使用 XML 格式定義影象,並且具有如下特點:

  • 不依賴解析度,基於向量圖;
  • 支援事件處理器;
  • 最適合帶有大型渲染區域的應用程式(比如谷歌地圖);
  • 複雜度高會減慢渲染速度(任何過度使用 DOM 的應用都不快);
  • 不適合遊戲應用;

來看一個簡單的示例,用SVG畫了一個圓:

SVG 程式碼以 元素開始,包括開啟標籤 和關閉標籤 。這是根元素。widthheight 屬性可設定此 SVG 文件的寬度和高度。version 屬性可定義所使用的 SVG 版本,xmlns 屬性可定義 SVG 名稱空間。

SVG 的 用來建立一個圓。cxcy 屬性定義圓中心的 x 和 y 座標。如果忽略這兩個屬性,那麼圓點會被設定為 (0, 0)。r屬性定義圓的半徑。

下面主要是介紹SVG中的幾個用於動畫的元素,它們分別是:

:通常放置到一個SVG影象元素裡面,用來定義這個影象元素的某個屬性的動畫變化過程;
:元素也是放置一個影象元素裡面,它可以引用一個事先定義好的動畫路徑,讓影象元素按路徑定義的方式運動;
:元素對圖形的運動和變換有更多的控制,它可以指定圖形的變換、縮放、旋轉和扭曲等;
:元素的用法在上面的例子裡出現過,它是一個輔助元素,通過它,等元素可以引用一個外部的定義的。讓影象元素按這個軌跡運動;

DEMO傳送門

WebGL

WebGL使得網頁在支援HTML 標籤的瀏覽器中,不需要安裝任何外掛,便可以使用基於 OpenGL ES 2.0 的 API 在 canvas 中進行3D渲染。 WebGL 程式由JavaScript的控制程式碼,和在計算機的圖形處理單元(GPU)中執行的特效程式碼(shader code,渲染程式碼) 組成。

2165169-d5eae2e535c672c9
WebGL.png

WebGL 本質上是基於光柵化的 API,而不是基於 3D 的 API。WebGL 只關注兩個方面,即投影矩陣的座標和投影矩陣的顏色。使用 WebGL 程式的任務就是實現具有投影矩陣座標和顏色的 WebGL 物件即可。可以使用“著色器”來完成上述任務。頂點著色器可以提供投影矩陣的座標,片段著色器可以提供投影矩陣的顏色。

由於WebGL的體系比較龐大,三言兩語說不完,所以以下僅提供各種傳送門了(不許說我懶!!):
WebGL 參考資料
WebGL API

幾個常用的動畫庫

Ani.js — 基於CSS動畫的生命處理庫
Dynamics.js — 建立具有物理運動效果動畫的js庫
Animate.css — 齊全的CSS3動畫庫
Three.js — 讓使用者通過javascript入手進入搭建webgl專案的類庫

 

相關文章