摘要:一個精簡的動畫庫實現項目地址由于項目須要做一些動畫,并不想讓整個項目引入太多的內容導致文件過大,所以為了滿足要求寫了一個精簡的可擴展的動畫庫功能是簡單模仿里面的函數用法這里的會返回到之間的數字再根據情況自己處理須要處理的動畫改變屬性到代碼過
一個精簡的js動畫庫實現 項目地址
animation.js
由于項目須要做一些動畫,并不想讓整個項目引入太多的內容導致文件過大,所以為了滿足要求寫了一個精簡的可擴展的動畫庫功能是簡單模仿d3.js里面的tween函數
用法:Animation() .easing(Animation.easing.Linear) .delay(500) .duration(1000) .run((i) => { // 這里的i會返回0到1之間的數字 // 再根據情況自己處理須要處理的動畫 // eg: 改變div left 屬性 10 到 100 document.querySelector(".box").style.left = 10 + 90 * i + "px" }) .then(() => { alert("finish") })代碼過程:
首先,須要一個緩動函數,這個網上一搜一大把
這里帖上一個
let easing = { Linea: 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 } }, Cubic: { easeIn: function (t, b, c, d) { return c * (t /= d) * t * t + b }, easeOut: function (t, b, c, d) { return c * ((t = t / d - 1) * t * t + 1) + b }, easeInOut: function (t, b, c, d) { if ((t /= d / 2) < 1) return c / 2 * t * t * t + b return c / 2 * ((t -= 2) * t * t + 2) + b } }, Quart: { easeIn: function (t, b, c, d) { return c * (t /= d) * t * t * t + b }, easeOut: function (t, b, c, d) { return -c * ((t = t / d - 1) * t * t * t - 1) + b }, easeInOut: function (t, b, c, d) { if ((t /= d / 2) < 1) return c / 2 * t * t * t * t + b return -c / 2 * ((t -= 2) * t * t * t - 2) + b } }, Quint: { easeIn: function (t, b, c, d) { return c * (t /= d) * t * t * t * t + b }, easeOut: function (t, b, c, d) { return c * ((t = t / d - 1) * t * t * t * t + 1) + b }, easeInOut: function (t, b, c, d) { if ((t /= d / 2) < 1) return c / 2 * t * t * t * t * t + b return c / 2 * ((t -= 2) * t * t * t * t + 2) + b } }, Sine: { easeIn: function (t, b, c, d) { return -c * Math.cos(t / d * (Math.PI / 2)) + c + b }, easeOut: function (t, b, c, d) { return c * Math.sin(t / d * (Math.PI / 2)) + b }, easeInOut: function (t, b, c, d) { return -c / 2 * (Math.cos(Math.PI * t / d) - 1) + b } }, Expo: { easeIn: function (t, b, c, d) { return (t == 0) ? b : c * Math.pow(2, 10 * (t / d - 1)) + b }, easeOut: function (t, b, c, d) { return (t == d) ? b + c : c * (-Math.pow(2, -10 * t / d) + 1) + b }, easeInOut: function (t, b, c, d) { if (t == 0) return b if (t == d) return b + c if ((t /= d / 2) < 1) return c / 2 * Math.pow(2, 10 * (t - 1)) + b return c / 2 * (-Math.pow(2, -10 * --t) + 2) + b } }, Circ: { easeIn: function (t, b, c, d) { return -c * (Math.sqrt(1 - (t /= d) * t) - 1) + b }, easeOut: function (t, b, c, d) { return c * Math.sqrt(1 - (t = t / d - 1) * t) + b }, easeInOut: function (t, b, c, d) { if ((t /= d / 2) < 1) return -c / 2 * (Math.sqrt(1 - t * t) - 1) + b return c / 2 * (Math.sqrt(1 - (t -= 2) * t) + 1) + b } }, Elastic: { easeIn: function (t, b, c, d, a, p) { if (t == 0) return b if ((t /= d) == 1) return b + c if (!p) p = d * 0.3 if (!a || a < Math.abs(c)) { a = c var s = p / 4 } else var s = p / (2 * Math.PI) * Math.asin(c / a) return -(a * Math.pow(2, 10 * (t -= 1)) * Math.sin((t * d - s) * (2 * Math.PI) / p)) + b }, easeOut: function (t, b, c, d, a, p) { if (t == 0) return b if ((t /= d) == 1) return b + c if (!p) p = d * 0.3 if (!a || a < Math.abs(c)) { a = c var s = p / 4 } else var s = p / (2 * Math.PI) * Math.asin(c / a) return (a * Math.pow(2, -10 * t) * Math.sin((t * d - s) * (2 * Math.PI) / p) + c + b) }, easeInOut: function (t, b, c, d, a, p) { if (t == 0) return b if ((t /= d / 2) == 2) return b + c if (!p) p = d * (0.3 * 1.5) if (!a || a < Math.abs(c)) { a = c var s = p / 4 } else var s = p / (2 * Math.PI) * Math.asin(c / a) if (t < 1) return -0.5 * (a * Math.pow(2, 10 * (t -= 1)) * Math.sin((t * d - s) * (2 * Math.PI) / p)) + b return a * Math.pow(2, -10 * (t -= 1)) * Math.sin((t * d - s) * (2 * Math.PI) / p) * 0.5 + c + b } }, Back: { easeIn: function (t, b, c, d, s) { if (s == undefined) s = 1.70158 return c * (t /= d) * t * ((s + 1) * t - s) + b }, easeOut: function (t, b, c, d, s) { if (s == undefined) s = 1.70158 return c * ((t = t / d - 1) * t * ((s + 1) * t + s) + 1) + b }, easeInOut: function (t, b, c, d, s) { if (s == undefined) s = 1.70158 if ((t /= d / 2) < 1) return c / 2 * (t * t * (((s *= (1.525)) + 1) * t - s)) + b return c / 2 * ((t -= 2) * t * (((s *= (1.525)) + 1) * t + s) + 2) + b } }, Bounce: { easeIn: function (t, b, c, d) { return c - Tween.Bounce.easeOut(d - t, 0, c, d) + b }, easeOut: function (t, b, c, d) { if ((t /= d) < (1 / 2.75)) { return c * (7.5625 * t * t) + b } else if (t < (2 / 2.75)) { return c * (7.5625 * (t -= (1.5 / 2.75)) * t + 0.75) + b } else if (t < (2.5 / 2.75)) { return c * (7.5625 * (t -= (2.25 / 2.75)) * t + 0.9375) + b } else { return c * (7.5625 * (t -= (2.625 / 2.75)) * t + 0.984375) + b } }, easeInOut: function (t, b, c, d) { if (t < d / 2) return Tween.Bounce.easeIn(t * 2, 0, c, d) * 0.5 + b else return Tween.Bounce.easeOut(t * 2 - d, 0, c, d) * 0.5 + c * 0.5 + b } } }
其次,我們須要用到requestAnimationFrame,要先解決一下兼容性問題
這個也是網上一找一大把,這里貼上我用的代碼
var vendors = ["webkit", "moz"] for (var x = 0; x < vendors.length && !window.requestAnimationFrame; ++x) { window.requestAnimationFrame = window[vendors[x] + "RequestAnimationFrame"] window.cancelAnimationFrame = window[vendors[x] + "CancelAnimationFrame"] || window[vendors[x] + "CancelRequestAnimationFrame"] } if (!window.requestAnimationFrame) { window.requestAnimationFrame = function (callback, element) { var currTime = new Date().getTime() var timeToCall = Math.max(0, 16.7 - (currTime - lastTime)) var id = window.setTimeout(function () { callback(currTime + timeToCall) }, timeToCall) lastTime = currTime + timeToCall return id } } if (!window.cancelAnimationFrame) { window.cancelAnimationFrame = function (id) { clearTimeout(id) } }
然后,我們須要定義一下時間戳的兼容函數,后面會用到
function time () { if (typeof performance !== "undefined" && performance.now) { return performance.now() } return Date.now ? Date.now() : (new Date()).getTime() }
最后,我們要開始制作整個動畫的主要內容了
核心是利用緩動函數進行目標值生成
緩動參數的說明:
t: 已經流逝的時間
b: 初始值
c: 目標值
d: 總時間
可以看出來緩動函數的大概功能是
根據 【t所占d的比例】
算出 【b-c之間的值】
我們只須要開始一個輪詢,傳入執行函數的時間和值直到結束就行了
下面看代碼
class AnimationCore { constructor () { this.__duration__ // 執行動畫的時間 this.__delay__ = 0 // 開始動畫的間隔 this.__action__ // 傳入的處理函數 this.__easing__ = easing.Linear // 緩動函數 this.__startTime__ // 開始動畫的時間戳 this.resolve = null this.timer = null } /** * 設置 執行動畫的時間 * */ duration (d) { this.__duration__ = d return this } /** * 設置 開始動畫的間隔 * */ delay (d) { this.__delay__ = d return this } /** * 設置 緩動函數 * */ easing (e) { this.__easing__ = e return this } /** * 停止 * */ stop () { if (this.timer) { cancelAnimationFrame(this.timer) this.timer = null } } /** * 結束并到最后狀態 * */ finish () { if (this.timer) { cancelAnimationFrame(this.timer) this.timer = null this.action(1) this.resolve() } } /** * 開始 動畫 * */ run (action, easingfunction) { return new Promise((resolve, reject) => { // 根據設置的delay來進行延時 setTimeout(() => { // 獲取開始時間 this.__startTime__ = time() easingfunction = easingfunction || this.__easing__ || easing.Linear this.action = action this.resolve = resolve // 這里先執行一次 因為下次執行時可能跳過了第一帖 this.action(0) // 下面是每貼要執行的內容 let step = () => { // 獲取流逝了的時間 var passedTime = Math.min(time() - this.__startTime__, this.__duration__) // 獲取0到1之間的值是通過緩動函數 // 參數說明: // t: 已經流逝的時間 // b: 初始值 // c: 目標值 // d: 總時間 this.action( easingfunction( passedTime, 0, 1, this.__duration__ ) ) if (passedTime >= this.__duration__) { this.start = null this.timer = null this.resolve() } else this.timer = requestAnimationFrame(step) } this.timer = requestAnimationFrame(step) }, this.__delay__) }) } }
導出內容
function Animation () { return new AnimationCore() } Animation.easing = easing // 導出 export default Animation
文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規行為,您可以聯系管理員刪除。
轉載請注明本文地址:http://specialneedsforspecialkids.com/yun/89689.html
摘要:超過的星星,是一個動畫庫,可以處理屬性,單個轉換,或任何屬性以及對象。超過星星,這個動畫庫大小只有。超過星星,這個庫基允許你以選定的速度為字符串創建打字動畫。 想閱讀更多優質文章請猛戳GitHub博客,一年百來篇優質文章等著你! 1.Three.js showImg(https://segmentfault.com/img/bVbkQ4X?w=551&h=358); 超過46K的星星,...
摘要:超過的,是一個動畫庫,可以處理屬性,單個轉換,或任何屬性以及對象。在,是一個快速的動畫引擎,具有與的相同的。在,這個功能和反應動畫庫只重。由和其他人使用,這個庫既流行又令人驚訝地有用。 在瀏覽網頁尋找一個整潔的Javascript動畫庫時,我發現很多recommended的動畫庫一段時間都沒有維護。 經過一些研究,我收集了11個最好的庫,在你的應用程序中使用。我還添加了一些,主要是非維...
摘要:超過的,是一個動畫庫,可以處理屬性,單個轉換,或任何屬性以及對象。在,是一個快速的動畫引擎,具有與的相同的。在,這個功能和反應動畫庫只重。由和其他人使用,這個庫既流行又令人驚訝地有用。 在瀏覽網頁尋找一個整潔的Javascript動畫庫時,我發現很多recommended的動畫庫一段時間都沒有維護。 經過一些研究,我收集了11個最好的庫,在你的應用程序中使用。我還添加了一些,主要是非維...
閱讀 1075·2021-09-29 09:35
閱讀 4621·2021-09-22 15:24
閱讀 1449·2021-07-25 21:37
閱讀 2178·2019-08-30 14:17
閱讀 965·2019-08-30 13:56
閱讀 2411·2019-08-29 17:07
閱讀 1250·2019-08-29 12:44
閱讀 2705·2019-08-26 18:26