題記:?當(dāng)你不再依賴JQuery時(shí),當(dāng)你已經(jīng)厭倦了引入js類庫實(shí)現(xiàn)一些動畫效果的方式,當(dāng)你想實(shí)現(xiàn)一個(gè)簡單而實(shí)用的動畫框架......下面介 紹下愚人設(shè)計(jì)的動畫框架:支持動畫緩動算法函數(shù),如Linear、Cubic、Back、Bounce,支持改變高度,寬度,透明度,邊框,外邊距的基本 動畫,支持動畫的回調(diào)函數(shù),如開始、暫停、完成的callback等。
?
?
?
Section One
?
游戲動畫,F(xiàn)lash動畫里一個(gè)比較重要的概念是 幀頻 ,即每秒播放多少幀動畫,一般動畫是30幀/秒,單位為fps(frames per second)。
?
對于勻速運(yùn)動來說:如果一個(gè)動畫的持續(xù)時(shí)間duration為500ms,幀頻frequence為30fps,則總幀數(shù)frames為
(500/1000)*30 = 15
,即該動畫過程有15個(gè)“畫面”,每走一幀,都計(jì)算出一個(gè)畫面:
畫面當(dāng)前位置 = 開始位置 + (當(dāng)前幀/總幀數(shù))(結(jié)束位置-開始位置)
,如果當(dāng)前幀是最后一幀,則動畫結(jié)束。其中setTimeout或setInterval每隔
(500/15)ms
時(shí)間段調(diào)用一次函數(shù),即計(jì)算一個(gè)畫面。
?
來看下線性運(yùn)動Linear緩動算法函數(shù),t表示當(dāng)前幀,b表示開始位置,c表示發(fā)生偏移的距離值,即當(dāng)前位置-開始位置,d表示總幀數(shù),符合上面 的推理解釋,對于其他的算法函數(shù),道理其實(shí)都是一樣,只不過在運(yùn)動過程中的曲線不同,有些呈現(xiàn)拋物線,有些呈現(xiàn)線性指數(shù),對于數(shù)學(xué)感興趣的可以研究下這些 算法函數(shù),我也是略知皮毛:
Linear: function (t, b, c, d) { return c * t / d + b; }
?
?
清楚了以上問題后,對于js的動畫框架設(shè)計(jì),就迎刃而解了,廢話不多說,來個(gè) demo 先。
?
?
Section Two
?
代碼總體結(jié)構(gòu),具體說明看注釋,需注意的問題: 1) 在私有作用域里定義的變量,要在外部能訪問到,需掛在window全局對象下,如window.Anim = Anim; 2) 動畫元素需要設(shè)置定位position屬性; 3) 傳入的外邊距參數(shù)需要駝峰式命名,并且當(dāng)同時(shí)設(shè)置targetPos(元素目標(biāo)位置)和外邊距時(shí),外邊距的值會覆蓋targetPos的值,如marginLeft的值會覆蓋targetPos.left的值,因?yàn)橥膺吘鄬?shí)現(xiàn)動畫的原理也是利用元素的left、top值:
(function(window) { /* * 工具對象 * 包含基本的dom操作,event操作 */ var util = {}; util.dom = { // 獲取元素計(jì)算樣式 getPropValue: function(element, propName) { }, // 設(shè)置透明度 setOpacity: function(obj, num) { document.all ? obj.filters.alpha.opacity = num : obj.style.opacity = num / 100; } // ...... }; util.event = { // 獲取事件對象 getEvent: function(event) { }, // 獲取事件源目標(biāo) getTarget: function(event) { }, // 注冊事件 addEvent: function(element, event, handler) { }, // 刪除事件 removeEvent: function(element, event, handler) { }, // 阻止默認(rèn)行為 preventDefault: function(event) { }, // 阻止事件冒泡 stopPropagation: function(event) { } // ...... }; /* * 動畫緩動函數(shù) */ 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 要執(zhí)行動畫的元素 * @options left、top、opacity、width、height、border、marginLeft、marginRight、marginTop、marginBottom */ function Anim(elem, options) { this.elem = elem; this.options = options; // 默認(rèn)樣式屬性 this.defaults = { }; } Anim.prototype = { constructor: Anim, // 初始化動畫 init: function() { this.isStart = false; this.isStop = false; this.isComplete = false; this.isBack = false; this.start(); }, // 初始化數(shù)據(jù) before: function() { }, // 開始動畫 start: function() { }, // 動畫過程 run: function() { this.before(); // 動畫參數(shù)匹配 this.match(); // 原路返回 if (this.isBack) { // ... } if (this.isStart) { this.onStart.call(this.elem); // 計(jì)算動畫 this.count(); } }, // 匹配動畫的參數(shù) match: function() { }, // 計(jì)算動畫 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);
?
Last
使用非常簡單,初始化參數(shù)對象,然后調(diào)用構(gòu)造函數(shù)Anim即可:
// 動畫參數(shù)設(shè)置 var options = { duration: 2000, // 動畫持續(xù)時(shí)間 frequence: 30, // 幀頻 tweenFunc: Tween.Linear, // 動畫緩動函數(shù) targetPos: {left: 400, top: 300}, // 元素目標(biāo)位置 opacity: 40, // 透明度(可選) width: 80, // 寬度(可選) height: 80, // 高度(可選) // marginTop: 100, // 上邊距(可選) border: '2px solid red', // 邊框(可選) // 動畫開始callback(可選) onStart: function() { // this指向當(dāng)前動畫元素 }, // 動畫停止callback(可選) onStop: function() { // this指向當(dāng)前動畫元素 }, // 動畫完成callback(可選) onComplete: function() { // this指向當(dāng)前動畫元素 } }; var anim = new Anim(animElem, options);
?
?
更多文章、技術(shù)交流、商務(wù)合作、聯(lián)系博主
微信掃碼或搜索:z360901061

微信掃一掃加我為好友
QQ號聯(lián)系: 360901061
您的支持是博主寫作最大的動力,如果您喜歡我的文章,感覺我的文章對您有幫助,請用微信掃描下面二維碼支持博主2元、5元、10元、20元等您想捐的金額吧,狠狠點(diǎn)擊下面給點(diǎn)支持吧,站長非常感激您!手機(jī)微信長按不能支付解決辦法:請將微信支付二維碼保存到相冊,切換到微信,然后點(diǎn)擊微信右上角掃一掃功能,選擇支付二維碼完成支付。
【本文對您有幫助就好】元
