JavaScript動畫實現初探
前言
現如今,許多頁面上均有一些動畫效果。適當的動畫效果可以在一定程度上提高頁面的美觀度,具有提示效果的動畫可以增強頁面的易用性。
實現頁面動畫的途徑有兩種。一種是通過操作JavaScript間接操作CSS樣式,每隔一段時間更新一次;一種是直接通過CSS定義動畫。第二種方法在CSS3成熟之後被廣泛採用。在本文中,我們討論第一種方法的原理和實現。
JavaScript動畫實現原理
首先我們需要知道兩個重要的概念,動畫時間程式和動畫效果程式。
動畫時間程式指從時間上看動畫的完成度,是一個[0, 1]之間的數字。假設動畫於時間戳t1
開始,要在t2
結束,當前時間戳為t
,那麼該動畫目前的時間程式為(t-t1)/(t2-t1)
。如果你不能理解,我建議你用紙筆畫出來。理解這一概念對理解本文至關重要。
動畫效果程式指被動畫的屬性值當前的增量。假設我們要將#el
元素的CSS left
屬性從100px
變到200px
,當前已經變到了130px
,那麼該動畫目前的效果程式為130px - 100px = 30px
。
假設動畫時間程式和動畫效果程式都是線性的。那麼如果知道了動畫時間程式,一定可以得到動畫效果程式。
根據這個解釋,我們很快可以編寫出一個線性的動畫。
(function() { var begin, // 開始動畫的時間 el, start, end, duration; var INTERVAL = 13; function now() { return (new Date).getTime(); } /** * 執行一步動畫(更新屬性) */ function _animLeft() { var pos = (now() - begin) / duration; if (pos >= 1.0) { return false; } return !!(el.style.left = start + (end - start) * pos); } /** * 對一個DOM執行動畫,left從_start到_end,執行時間為 * _duration毫秒。 * * @param {object} _el 要執行動畫的DOM節點 * @param {integer} _start left的起始值 * @param {integer} _end left的最終值 * @param {integer} _duration 動畫執行時間 */ function animLeft(_el, _start, _end, _duration) { stopped = false; begin = now(); el = _el; start = _start; end = _end; duration = _duration || 1000; var step = function() { if (_animLeft()) { setTimeout(step, INTERVAL); } }; setTimeout(step, 0); } window.animLeft = animLeft; })(); animLeft( document.getElementById('el'), 100, 200 )
easing
很多時候,我們需要的動畫並非線性的。所謂非線性,從直觀上看,就是動畫速度隨著時間會產生變化。那麼如何實現變速的動畫呢?
由前所述,我們知道通過控制動畫的時間程式就相當於控制動畫的效果程式。隨著真實世界的時間程式推移,動畫的時間程式跟著推移,從而控制動畫的效果程式推移。那麼,我們可以通過修改真實世界的時間程式和動畫的時間程式間的對映關係,從而控制動畫程式。如果你感到困惑,沒關係,請看下圖:
這是線性動畫中,真實世界的時間程式和動畫程式的對映關係。接下來,我們將其進行變換
這條曲線實際上是函式y = x * x
的影像。可以看到,兩個曲線的定義域和值域並沒有變化。曲線的斜率就是動畫的速率。接下來我們將兩張圖重疊在一起做一個對比。
在真實世界的時間進行到x0
的時候,動畫程式原本應該進行到y0
,在進行變換之後,只進行到y1
。到最後,百川歸海,兩條線交匯於點(1, 1)。這裡,y = x * x
是變換函式(easing function)。
我們修改一下上面的例子,讓動畫變成非線性的。
function ease(time) { return time * time; } /** * 執行一步動畫(更新屬性) */ function _animLeft() { var pos = (now() - begin) / duration; if (pos >= 1.0) { return false; } pos = ease(pos); return !!(el.style.left = (start + (end - start) * pos) + "px"); }
我們可以在jQuery的程式碼中看到這樣的函式。
jQuery.easing = { linear: function( p ) { return p; }, swing: function( p ) { return 0.5 - Math.cos( p * Math.PI ) / 2; } };
因此,你可以往jQuery.easing裡面新增easing function,使得jQuery支援新的動畫速率控制方法。注意,easing function的定義域和值域必須都為[0, 1]。
jQuery.easing.myEasing = function( p ) { return ... }
總結
本文介紹了JavaScript動畫的最基本的原理。
JavaScript動畫實質上也是通過操作CSS去執行動畫。動畫的時間程式可以決定動畫的效果程式。通過操作真實世界的時間程式和動畫的時間程式之間的關係,我們可以將線性動畫變換成非線性的動畫。
相關文章
- Javascript實現動畫效果JavaScript動畫
- 高效動畫實現原理-Jetpack Compose 初探索動畫Jetpack
- 用JavaScript實現動畫效果 (轉)JavaScript動畫
- javascript實現文字拼寫動畫效果JavaScript動畫
- javascript實現animate()動畫效果程式碼例項JavaScript動畫
- 實現元素動畫的6款 JavaScript 外掛動畫JavaScript
- Android 動畫初探Android動畫
- React Native學習實踐:動畫初探之載入動畫React Native動畫
- javascript實現的動畫效果簡單例項程式碼JavaScript動畫單例
- Flutter實現動畫Flutter動畫
- three.js之初探骨骼動畫JS動畫
- Android 動畫實現Android動畫
- iOS實現字串動畫iOS字串動畫
- React實現動畫效果React動畫
- Javascript動畫(一)JavaScript動畫
- Javascript 之 Event Looooooop 初探JavaScriptOOP
- 初探 JavaScript 物件導向JavaScript物件
- jQuery中動畫的實現jQuery動畫
- canvas之實現控制動畫Canvas動畫
- Flutter 實現背景 Parallax 動畫Flutter動畫
- Android 動畫框架實現Android動畫框架
- WPF簡單動畫實現動畫
- .Net Core實現區塊鏈初探區塊鏈
- Quill編輯器實現原理初探UI
- Flutter實戰之動畫實現篇Flutter動畫
- Flutter動畫:用Flutter來實現一個拍手動畫Flutter動畫
- 《JavaScript 闖關記》之初探JavaScript
- 大話 JavaScript 動畫JavaScript動畫
- JavaScript元素動畫效果JavaScript動畫
- Kubernetes 排程器實現初探
- Flutter動畫實現粒子漂浮效果Flutter動畫
- Flutter動畫實現原理淺析Flutter動畫
- JS 實現拋物線動畫JS動畫
- CSS3實現流星動畫CSSS3動畫
- 使用canvas實現簡單動畫Canvas動畫
- [譯] 使用 Swift 實現原型動畫Swift原型動畫
- Android動畫實現詳解Android動畫
- 主流動畫實現方式總結動畫