在本系列的第一部分中,我們只是開始熟悉Fabric.js。我們研究了使用Fabric的原因,物件模型和物件層次結構,Fabric中可用的不同種類的實體-簡單的形狀,圖像和複雜的路徑。我們也學習如何對畫布上的Fabric物件執行簡單的操作。
既然大多數基本知識都結束了,那麼讓我們開始一些有趣的事情吧!
Animation
沒有動畫工具的canvas庫是不會受人尊重的。而且Fabric也不例外。由於具有如此強大的物件模型和圖形功能,因此如果沒有內建動畫助手將是很可惜的。
還記得更改任何物件的屬性有多容易嗎?我們只是呼叫了set方法,並傳遞了對應的值:
rect.set("angle",45)
好吧,為物件設定動畫同樣容易。每個Fabric物件都有一個animate方法,該方法可以動畫化該物件。
rect.animate('angle', 45, {
onChange: canvas.renderAll.bind(canvas)
});
第一個參數是要設定動畫的屬性。第二個參數是動畫的結束值。如果矩形具有-15°的角度,並且我們傳遞了45,則動畫將從-15°變為45°。第三個參數是一個可選對象,用於指定動畫的詳細資訊-持續時間,回調,緩動等。
animate的一個便利功能是它也支援相對值。例如,如果您想為物件的left屬性設定100px的動畫,則可以這樣做:
rect.animate('left', '+=100', { onChange: canvas.renderAll.bind(canvas) });
同樣,可以將物件逆時針旋轉5度,如下所示:
rect.animate('angle', '-=5', { onChange: canvas.renderAll.bind(canvas) });
您可能想知道為什麼我們總是在此處指定“ onChange”回調。第三個參數不是可選的嗎?是的,但是在每個動畫幀上調用canvas.renderAll才使我們能夠看到實際的動畫!您會看到,當我們呼叫animate方法時,它只會按照特定演算法(即緩動)隨時間對屬性值進行動畫處理。因此,rect.animate('angle',45)將更改物件的角度,但在每次更改角度後都不會重新渲染畫布螢幕。我們顯然需要重新渲染才能看到實際的動畫。
您可能想知道為什麼我們總是在此處指定“ onChange”回調。第三個參數不是可選的嗎?是的,但是在每個動畫幀上調用canvas.renderAll才使我們能夠看到實際的動畫!您會看到,當我們呼叫animate方法時,它只會按照特定演算法(即緩動)隨時間對屬性值進行動畫處理。因此,rect.animate('angle',45)將更改物件的角度,但在每次更改角度後都不會重新渲染畫布螢幕。我們顯然需要重新渲染才能看到實際的動畫。
請記住,在畫布表面下方有整個物件模型。物件具有自己的屬性和關係,而畫布僅負責將它們的存在投射到外部世界。
每次更改後動畫沒有自動重新渲染畫布的原因是由於效能。畢竟,我們可以在畫布上有成百上千個動畫對象,如果每個對像都試圖重新渲染螢幕並不是很好。對於許多對象,您可以使用諸如requestAnimationFrame(或其他基於計時器的)循環之類的東西連續不斷地渲染畫布,而無需為每個對象調用renderAll。但是大多數時候,您可能需要明確指定canvas.renderAll作為「 onChange」回呼。
那我們可以傳遞哪些其他選項來進行動畫處理呢?
from:允許指定可設定動畫的屬性的起始值(如果我們不希望使用目前值)。
duration:預設為500(ms)。可用於更改動畫的持續時間。
onComplete:在動畫結束時呼叫的回呼。
easing:緩動功能。
所有這些選擇都應該是不言自明的,除非可能是個簡單的選擇。讓我們仔細看看。
預設情況下,animate使用「 easeInSine」功能進行動畫處理。如果這不是您所需要的,那麼fabric.util.ease下提供了許多寬鬆選項。例如,如果我們想以彈性的方式將物件向右移動:
rect.animate('left', 500, {
onChange: canvas.renderAll.bind(canvas),
duration: 1000,
easing: fabric.util.ease.easeOutBounce
});
請注意fabric.util.ease.easeOutBounce是一個緩和選項。其他值得注意的包括easeInCubic、easeOutCubic、easeInElastic、easeOutElastic和easeOutExpo。
因此,這涵蓋了Fabric的動畫部分。只是給您一些可能的想法-您可以為對象的角度設置動畫以使其旋轉。動畫左/上屬性以使其移動;動畫寬度/高度,使其縮小/增長;為不透明度設置動畫以使其淡入/淡出;等等。
fabric.runningAnimations
如果需要存取目前按結構運行的動畫,請使用fabric.runningAnimations。它是一個物件數組,每個物件都是動畫上下文物件。
簡便的方法:
fabric.runningAnimations.findAnimation(signature)-傳回動畫上下文符合簽名,該簽名是fabric.util.animate回傳的中止函數。
fabric.runningAnimations.findAnimationIndex(簽名)-與findAnimation相同,回傳索引。
fabric.runningAnimations.findAnimationsByTarget(target)-傳回目標屬性等於target的所有動畫。
fabric.runningAnimations.cancelAll()-取消所有正在運行的動畫。
fabric.runningAnimations.cancelByTarget(target)-取消目標屬性等於target的動畫。
object.dispose()-取消物件(object.animate(…))所建立的所有動畫。如果要使用fabric.util.animate而不是object.animate(…)來新增動畫,可以透過傳遞目標屬性將其附加到物件。這樣,一旦物件被釋放,動畫將被取消。
let cancel = fabric.util.animate({...});
let i = fabric.runningAnimations.findAnimationIndex(cancel);
let context = fabric.runningAnimations.findAnimation(cancel);
let cancelled = fabric.runningAnimations.cancelAll();
// the following statements are true
cancelled[i] === context;
cancelled[i].cancel === cancel;
fabric.runningAnimations.length === 0;