題記: 當你再也不依賴JQuery時,當你已經厭倦了引入js類庫實現一些動畫效果的方式,當你想實現一個簡單而實用的動畫框架......下面介紹下愚人設計的動畫框架:支持動畫緩動算法函數,如Linear、Cubic、Back、Bounce,支持改變高度,寬度,透明度,邊框,外邊距的基本動畫,支持動畫的回調函數,如開始、暫停、完成的callback等。html
遊戲動畫,Flash動畫裏一個比較重要的概念是幀頻,即每秒播放多少幀動畫,通常動畫是30幀/秒,單位爲fps(frames per second)。git
對於勻速運動來講:若是一個動畫的持續時間duration爲500ms,幀頻frequence爲30fps,則總幀數frames爲(500/1000)*30 = 15
,即該動畫過程有15個「畫面」,每走一幀,都計算出一個畫面:畫面當前位置 = 開始位置 + (當前幀/總幀數)(結束位置-開始位置)
,若是當前幀是最後一幀,則動畫結束。其中setTimeout或setInterval每隔(500/15)ms
時間段調用一次函數,即計算一個畫面。github
來看下線性運動Linear緩動算法函數,t表示當前幀,b表示開始位置,c表示發生偏移的距離值,即當前位置-開始位置,d表示總幀數,符合上面的推理解釋,對於其餘的算法函數,道理其實都是同樣,只不過在運動過程當中的曲線不一樣,有些呈現拋物線,有些呈現線性指數,對於數學感興趣的能夠研究下這些算法函數,我也是略知皮毛:算法
Linear: function (t, b, c, d) { return c * t / d + b; }
清楚了以上問題後,對於js的動畫框架設計,就迎刃而解了,廢話很少說,來個 demo 先。框架
代碼整體結構,具體說明看註釋,需注意的問題:1)在私有做用域裏定義的變量,要在外部能訪問到,需掛在window全局對象下,如window.Anim = Anim;2)動畫元素須要設置定位position屬性;3)傳入的外邊距參數須要駝峯式命名,而且當同時設置targetPos(元素目標位置)和外邊距時,外邊距的值會覆蓋targetPos的值,如marginLeft的值會覆蓋targetPos.left的值,由於外邊距實現動畫的原理也是利用元素的left、top值:dom
(function(window) { /* * 工具對象 * 包含基本的dom操做,event操做 */ var util = {}; util.dom = { // 獲取元素計算樣式 getPropValue: function(element, propName) { }, // 設置透明度 setOpacity: function(obj, num) { document.all ? obj.filters.alpha.opacity = num : obj.style.opacity = num / 100; } // ...... }; util.event = { // 獲取事件對象 getEvent: function(event) { }, // 獲取事件源目標 getTarget: function(event) { }, // 註冊事件 addEvent: function(element, event, handler) { }, // 刪除事件 removeEvent: function(element, event, handler) { }, // 阻止默認行爲 preventDefault: function(event) { }, // 阻止事件冒泡 stopPropagation: function(event) { } // ...... }; /* * 動畫緩動函數 */ var Tween = { Linear: function (t, b, c, d) { return c * t / d + b; }, Quad: { easeIn: function (t, b, c, d) { return c * (t /= d) * t + b; }, easeOut: function (t, b, c, d) { return -c * (t /= d) * (t - 2) + b; }, easeInOut: function (t, b, c, d) { if ((t /= d / 2) < 1) return c / 2 * t * t + b; return -c / 2 * ((--t) * (t - 2) - 1) + b; } }, // ... }; /* * 核心動畫 * @elem 要執行動畫的元素 * @options left、top、opacity、width、height、border、marginLeft、marginRight、marginTop、marginBottom */ function Anim(elem, options) { this.elem = elem; this.options = options; // 默認樣式屬性 this.defaults = { }; } Anim.prototype = { constructor: Anim, // 初始化動畫 init: function() { this.isStart = false; this.isStop = false; this.isComplete = false; this.isBack = false; this.start(); }, // 初始化數據 before: function() { }, // 開始動畫 start: function() { }, // 動畫過程 run: function() { this.before(); // 動畫參數匹配 this.match(); // 原路返回 if (this.isBack) { // ... } if (this.isStart) { this.onStart.call(this.elem); // 計算動畫 this.count(); } }, // 匹配動畫的參數 match: function() { }, // 計算動畫 count: function() { }, // 原路返回 back: function() { }, // 中止動畫 stop: function() { }, // 重置元素 reset: function() { } }; // 全局使用 if (!window.util) { window.util = util; } if (!window.Anim) { window.Anim = Anim; } if (!window.Tween) { window.Tween = Tween; } })(window);
使用很是簡單,初始化參數對象,而後調用構造函數Anim便可:ide
// 動畫參數設置 var options = { duration: 2000, // 動畫持續時間 frequence: 30, // 幀頻 tweenFunc: Tween.Linear, // 動畫緩動函數 targetPos: {left: 400, top: 300}, // 元素目標位置 opacity: 40, // 透明度(可選) width: 80, // 寬度(可選) height: 80, // 高度(可選) // marginTop: 100, // 上邊距(可選) border: '2px solid red', // 邊框(可選) // 動畫開始callback(可選) onStart: function() { // this指向當前動畫元素 }, // 動畫中止callback(可選) onStop: function() { // this指向當前動畫元素 }, // 動畫完成callback(可選) onComplete: function() { // this指向當前動畫元素 } }; var anim = new Anim(animElem, options);
最後附上 源代碼 以及easing算法函數的 demo。函數
認真對待每個人,每一件事,會有意想不到的收穫!工具