緩動函數和三角函數在前端動畫開發中的應用

1、導言

前端開發中,動畫實現方式有兩種:CSS動畫和JS動畫,因爲渲染方式的不一樣,CSS動畫相對JS動畫性能較好,故優先使用CSS來完成須要的動畫效果,可是,在CSS動畫沒法實現(好比點擊網站底部回到頂部)以及須要控制動畫暫停、播放、彈跳、倒退或減速等場景下,咱們就得使用JS動畫,那如何經過JS編寫一個符合天然運動規律、高性能的動畫呢?下面,我會經過實現一個完整動畫案例來一一展開介紹。css

2、目標分解

咱們的目的有兩個:前端

  1. 符合天然運動規律
  2. 高性能

符合天然運動規律就是指動畫應該符合現實物體運動規律,現實物體是按照必定節奏運動的,並非一成不變的,好比你向空中拋一個球,球飛向空中的速度是先加速而後逐漸減速的,因此咱們的動畫應該是有生命力的,可以符合人們對現實現象認知的。git

高性能就是指層如今人們眼睛裏的畫面無卡頓,畫面始終以一個接近恆定的刷新頻率(目標是60FPS)進行渲染的。由於根據人眼睛的視覺停留效應,若前一幅畫像停留在大腦中的印象還沒消失,後一幅畫像接踵而至,而且兩副畫像間的差異很小,就會有「動」的感受,因此咱們的動畫的渲染應該維持一個接近恆定的頻率,這也是高性能動畫的關鍵。github

3、高性能動畫

在動手實現咱們的實際案例以前,我想而外介紹下高性能動畫的關鍵點。瞭解瀏覽器渲染機制的童鞋應該都知道,在瀏覽器構建完DOM樹以及CSSOM以後,就會進入到實際的渲染階段,渲染通常通過重排、重繪和合成三個階段。常見的移動元素(left、top等屬性),變換元素大小等,都會致使元素從新經歷重排和重繪和合成三個階段,有關對指定的屬性設置動畫會觸發哪一個動做的詳細信息,能夠查看csstriggersweb

於是,要想動畫性能高,咱們就要儘可能減小渲染路徑,好比只觸發重繪或者合成,從而提升動畫性能。好比經過transform變換元素位置就會只觸發合成階段,於是性能較高。其它可以提高動畫性能的方式有:算法

  1. 動畫元素脫離文檔流,防止動畫致使其它元素從新渲染
  2. 儘可能使用CSS3的transitionanimation實現動畫(瀏覽器會有專門的合成器線程處理動畫,不影響主線程上的任務)
  3. 使用will-change提早告訴瀏覽器單獨開闢一個線程處理動畫
  4. 使用相似transform``opacity等只觸發合成階段的屬性實現動畫效果
  5. 等等

4、三角函數與緩動函數

三角函數,學生時代確定學過,是以角度(數學上最經常使用弧度制)爲自變量,角度對應任意角終邊與單位圓交點座標或其比值爲因變量的函數,在研究三角形和圓等幾何形狀的性質時有重要做用,也是研究週期性現象的基礎數學工具。有點繞,不過我以爲只要知道經過它能夠獲取一組週期性數據,利用這組週期性數據,能夠完成周期性動畫或者生成周期性曲線便可,後面會有實際例子說明,更多關於三角函數的能夠查看這篇文章瀏覽器

以正弦曲線爲例,正弦曲線公式:y = A sin(Bx + C) + D,其中各個參數的意義以下:wordpress

A 控制振幅,A 值越大,波峯和波谷越大,A 值越小,波峯和波谷越小; B 值會影響週期,B 值越大,那麼週期越短,B 值越小,週期越長。 C 值會影響圖像左右移動,C 值爲正數,圖像右移,C 值爲負數,圖像左移。 D 值控制上下移動。函數

經過調整A、B、C、D值就能夠獲得咱們想要的曲線效果,這個網站能夠可視化查看各類三角函數的曲線效果。工具

緩動函數,區別於勻速運動,緩動函數給咱們提供了隨着時間變化按照非勻速變化運動的一種方式,點擊這裏能夠查看各類不一樣的緩動曲線,github上流行的tween.js庫就是一個具體實現的庫。關於緩動函數的更多介紹能夠查看如何使用Tween.js各種原生動畫運動緩動算法

緩動函數主要用來調整動畫的速率,以下方塊從左到右,到底部反彈再回到底部,案例地址

能夠看出,緩動函數能使動畫看起來更天然而且符合現實運動規律,應該銘記於心的是咱們在處理任何動畫時都應該添加緩動效果,而且根據現實世界的一個潛意識規律定義緩動函數,使動畫看起來更生動。

5、案例效果

普及完基礎知識後,咱們來說下咱們須要實現的案例,下面就是咱們須要實現的動畫效果,直播工具中常見的點擊飄心動畫。

這個案例功能很簡單,就是點擊桃心,隨機出現不一樣顏色的桃心,以不規則的曲線向上飄動,而後逐漸消失,因爲須要控制動畫路徑以及動態生成動畫元素,CSS動畫沒法實現,故咱們將會採用JS來實現。

6、具體實現

首先,咱們須要監聽點擊事件,生成一個桃心元素,代碼以下:

接着,生成的桃心以非直線路徑向上飄動,這個路徑的生成咱們就可使用三角函數來實現,咱們這裏用到了正弦、餘弦、正切三種三角函數,分別對應左、中、右三個方向,這三個三角函數的生成返回的值的值域都是[-1,1],配合振幅、偏移量以及元素的基礎位置等參數,咱們就能夠生成一個相似正弦、餘弦、正切的路徑曲線。

以正弦曲線爲例,生成一個正弦曲線路徑的代碼以下,其中,deg * Math.PI / 180爲角度轉弧度,10表明振幅,注意這裏振幅不能太大,不然會超出視圖邊緣,減2.5表明偏移量,能夠自行調整。

生成三條路徑曲線的代碼:

接下來須要讓桃心按照咱們的路徑曲線動起來,就須要隨時調整元素的位置,首先咱們想到的是使用setTimeout或者setInterval,按照1000 / 60 = 16.7ms間隔時間執行位移函數(FPS爲60,平均繪製一幀須要16.7ms),然而因爲瀏覽器中的頁面循環系統(Event Loop)的緣由,setTimeout的回調函數有可能不必定是按照咱們指定的間隔時間執行的(任務隊列裏面可能摻雜其它微任務),具體緣由讀者能夠本身去查閱,從而可能會致使動畫渲染沒法按照規律的刷新頻率進行渲染,視覺上看起來就會有卡頓現象。

所以,瀏覽器提供了requestAnimationFrame來專門應對這種狀況,它的用法等同於setTimeout,在下一個瀏覽器刷新週期執行回調函數,只不過每次的間隔時間由瀏覽器控制,不須要咱們主動定義,於是渲染性能最高,使用js動畫通常都是使用這個方法。

另外,動畫位置偏移,咱們使用tranform中的translate進行位移,而不是使用lefttop,緣由是translate只會觸發元素從新進入合成階段,相比使用lefttop觸發重繪、重排,資源消耗更低,於是性能更高。

桃心運動的代碼以下:

此時,來看下咱們的動畫效果

同時看下性能,很好,FPS鋸齒很平整,頻率也接近60FPS,表明動畫渲染性能較高。

大部分人作到這裏估計就結束了,可是回想一下文章一開始說的,咱們的目的是建立一個==高性能且符合天然運動規律==的動畫,放到這裏就是桃心向上飄動的過程速度應該是先加速而後不斷下降的,而不是一成不變的。

故此,引入了緩動函數來調整速率,這裏咱們選擇了緩出,它開頭較快,使動畫有反應快速的感受,且結尾有個不錯的減速,很是適合咱們的場景,更多緩動動畫函數查看easings,這裏咱們的目的是調整Y軸方向上速率,代碼以下:

最後再看下咱們動畫效果,桃心向上飄動先加速後減速,很是天然。

至此,咱們的動畫纔算完成。

7、總結

經過這篇文章,我介紹了三角函數和緩動函數在動畫中的運用,指出了實現高性能動畫的一些關鍵細節,以及如何去實現符合天然運動規律的動畫,雖然個別地方不是很深刻,但但願個人文章可以給你一個指引,在之後的工做開發中,碰到動畫處理更加駕輕就熟,知道該如何實現高效能且符合天然運動規律的動畫。

以上完整代碼能夠在個人codepen查看,另外,訪問個人github能夠查看個人更多文章。

8、參考資料

相關文章
相關標籤/搜索