摘要:使用了緩動(dòng)函數(shù),只需要通過當(dāng)前動(dòng)畫消耗的時(shí)間,搭配其他定義的配置項(xiàng),就可以計(jì)算出當(dāng)前動(dòng)畫具體位置。此次解析就到這里結(jié)束,如有錯(cuò)誤,請(qǐng)指出,感謝
本次解析將分為2篇文章,當(dāng)前是第二篇,第一篇在這里
另外,為了能更好的理解這個(gè)庫(kù),個(gè)人寫了一個(gè)此庫(kù)的壓縮版,實(shí)現(xiàn)了核心的功能(主要也是為了更好理解核心功能),內(nèi)容更少方便閱讀,
地址在這里
繼續(xù)上一篇,先把結(jié)構(gòu)圖拉過來:
// anime主體 function anime(params){ // 定義instance 也是最終返回值 let instance = createNewInstance(params); // 外部API 從當(dāng)前位置開始執(zhí)行動(dòng)畫 instance.play = function() {} // 配置 startTime 和 engineTime(關(guān)鍵) instance.tick = function(t) {} // 對(duì)當(dāng)前engineTime進(jìn)行判斷,確定動(dòng)畫方案(關(guān)鍵) function setInstanceProgress(engineTime) {} // 計(jì)算動(dòng)畫當(dāng)前位置 并且賦值(關(guān)鍵) function setAnimationsProgress(insTime){} // 直接跳到參數(shù)time的時(shí)間所在的位置 instance.seek = function(time) {} // 外部API 暫停 instance.pause = function() {} // 外部API 反轉(zhuǎn) instance.reverse = function() {} // 外部API reset instance.reset = function() {} // 外部API 重新開始 instance.restart = function() {} /*...*/ return instance }
setAnimationsProgress(省略了一些配置的定義)
這個(gè)函數(shù)接受一個(gè)參數(shù),就是當(dāng)前位置所消耗時(shí)間(動(dòng)畫起始點(diǎn)),然后在里面計(jì)算出每一個(gè)動(dòng)畫目標(biāo)的位置,并且賦值
// 計(jì)算動(dòng)畫當(dāng)前位置 并且賦值 function setAnimationsProgress(insTime) { /* ... */ // 這個(gè)while逐個(gè)計(jì)算當(dāng)前實(shí)例中的每個(gè)動(dòng)畫的當(dāng)前位置(通過時(shí)間和算法) while (i < animationsLength) { /* ... */ // 消耗的時(shí)間占總持續(xù)時(shí)間的比例 在起點(diǎn)終點(diǎn)之間 const elapsed = minMaxValue(insTime - tween.start - tween.delay, 0, tween.duration) / tween.duration; // 通過算法計(jì)算當(dāng)前進(jìn)度 const eased = isNaN(elapsed) ? 1 : tween.easing(elapsed, tween.elasticity); /* ... */ // 遍歷每一個(gè)到達(dá)點(diǎn)執(zhí)行 for (let n = 0; n < toNumbersLength; n++) { let value; const toNumber = tween.to.numbers[n]; const fromNumber = tween.from.numbers[n]; if (!tween.isPath) { // 計(jì)算當(dāng)前具體位置 value = fromNumber + (eased * (toNumber - fromNumber)); } else { // 進(jìn)行SVG path計(jì)算 value = getPathProgress(tween.value, eased * toNumber); } /* ... */ numbers.push(value); } /* ... */ if (!isNaN(n)) { // 組合單位 "135.546"+"px" if (!b) { progress += n + " "; } else { progress += n + b; } } /* ... */ // 組合結(jié)果 "translateX("+"135.546px"+")` setTweenProgress[anim.type](animatable.target, anim.property, progress, transforms, animatable.id); anim.currentValue = progress; i++; } // 遍歷結(jié)果,逐個(gè)target賦值 const transformsLength = Object.keys(transforms).length; if (transformsLength) { for (let id = 0; id < transformsLength; id++) { if (!transformString) { const t = "transform"; // 配置兼容性 transformString = (getCSSValue(document.body, t) ? t : `-webkit-${t}`); } // 設(shè)置style instance.animatables[id].target.style[transformString] = transforms[id].join(" "); } } // 記錄當(dāng)前位置所對(duì)應(yīng)的時(shí)間 instance.currentTime = insTime; // 設(shè)置進(jìn)度 instance.progress = (insTime / instance.duration) * 100; }
剩下的就是一些操作函數(shù)了:
instance.seek
// 直接跳到參數(shù)time的時(shí)間所在的位置 instance.seek = function(time) { setInstanceProgress(adjustTime(time)); }
instance.pause
// 外部API 暫停 instance.pause = function() { const i = activeInstances.indexOf(instance); // 刪除activeInstances 后續(xù)engine中找不到便不會(huì)執(zhí)行 if (i > -1) activeInstances.splice(i, 1); instance.paused = true; }
instance.reverse
// 外部API 反轉(zhuǎn) instance.reverse = function() { toggleInstanceDirection(); startTime = 0; lastTime = adjustTime(instance.currentTime); }
instance.restart
// 外部API 重新執(zhí)行 instance.restart = function() { instance.pause(); instance.reset(); instance.play(); }
instance.reset
// 外部API reset instance.reset = function() { const direction = instance.direction; const loops = instance.loop; // 當(dāng)前位置,進(jìn)度 歸零 instance.currentTime = 0; instance.progress = 0; instance.paused = true; instance.began = false; instance.completed = false; instance.reversed = direction === "reverse"; instance.remaining = direction === "alternate" && loops === 1 ? 2 : loops; setAnimationsProgress(0); for (let i = instance.children.length; i--; ){ instance.children[i].reset(); } }總結(jié)
使用了requestAnimateFrame和CSS動(dòng)畫提高流暢度。
使用了緩動(dòng)函數(shù),只需要通過當(dāng)前動(dòng)畫消耗的時(shí)間,搭配其他定義的配置項(xiàng),就可以計(jì)算出當(dāng)前動(dòng)畫具體位置。
此次解析就到這里結(jié)束,如有錯(cuò)誤,請(qǐng)指出,感謝!
文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請(qǐng)注明本文地址:http://systransis.cn/yun/97745.html
摘要:初始位置結(jié)束位置和持續(xù)時(shí)間是作為參數(shù)傳入配置的,因此計(jì)算已消耗時(shí)間就是完成動(dòng)畫的核心。下面就深入了解下它的核心。 本次解析將分為2篇文章,當(dāng)前是第一篇,第二篇在這里 另外,為了能更好的理解這個(gè)庫(kù),個(gè)人寫了一個(gè)此庫(kù)的壓縮版,實(shí)現(xiàn)了核心的功能(主要也是為了更好理解核心功能),內(nèi)容更少方便閱讀,地址在這里 介紹 anime一個(gè)JS輕量動(dòng)畫庫(kù),摒棄了常規(guī)的left,top屬性,全面采用req...
摘要:超過的,是一個(gè)動(dòng)畫庫(kù),可以處理屬性,單個(gè)轉(zhuǎn)換,或任何屬性以及對(duì)象。在,是一個(gè)快速的動(dòng)畫引擎,具有與的相同的。在,這個(gè)功能和反應(yīng)動(dòng)畫庫(kù)只重。由和其他人使用,這個(gè)庫(kù)既流行又令人驚訝地有用。 在瀏覽網(wǎng)頁(yè)尋找一個(gè)整潔的Javascript動(dòng)畫庫(kù)時(shí),我發(fā)現(xiàn)很多recommended的動(dòng)畫庫(kù)一段時(shí)間都沒有維護(hù)。 經(jīng)過一些研究,我收集了11個(gè)最好的庫(kù),在你的應(yīng)用程序中使用。我還添加了一些,主要是非維...
摘要:超過的,是一個(gè)動(dòng)畫庫(kù),可以處理屬性,單個(gè)轉(zhuǎn)換,或任何屬性以及對(duì)象。在,是一個(gè)快速的動(dòng)畫引擎,具有與的相同的。在,這個(gè)功能和反應(yīng)動(dòng)畫庫(kù)只重。由和其他人使用,這個(gè)庫(kù)既流行又令人驚訝地有用。 在瀏覽網(wǎng)頁(yè)尋找一個(gè)整潔的Javascript動(dòng)畫庫(kù)時(shí),我發(fā)現(xiàn)很多recommended的動(dòng)畫庫(kù)一段時(shí)間都沒有維護(hù)。 經(jīng)過一些研究,我收集了11個(gè)最好的庫(kù),在你的應(yīng)用程序中使用。我還添加了一些,主要是非維...
摘要:超過的,是一個(gè)動(dòng)畫庫(kù),可以處理屬性,單個(gè)轉(zhuǎn)換,或任何屬性以及對(duì)象。在,是一個(gè)快速的動(dòng)畫引擎,具有與的相同的。在,這個(gè)功能和反應(yīng)動(dòng)畫庫(kù)只重。由和其他人使用,這個(gè)庫(kù)既流行又令人驚訝地有用。 在瀏覽網(wǎng)頁(yè)尋找一個(gè)整潔的Javascript動(dòng)畫庫(kù)時(shí),我發(fā)現(xiàn)很多recommended的動(dòng)畫庫(kù)一段時(shí)間都沒有維護(hù)。 經(jīng)過一些研究,我收集了11個(gè)最好的庫(kù),在你的應(yīng)用程序中使用。我還添加了一些,主要是非維...
閱讀 2538·2023-04-26 02:57
閱讀 1420·2023-04-25 21:40
閱讀 2198·2021-11-24 09:39
閱讀 3572·2021-08-30 09:49
閱讀 779·2019-08-30 15:54
閱讀 1181·2019-08-30 15:52
閱讀 2096·2019-08-30 15:44
閱讀 1284·2019-08-28 18:27