[英]Fabric.js animate object/image
大家好,這是我一直在使用的代碼。 它將一個對象從 A 移動到 B。我想要做的是讓它移動到多個點。 所以從起始位置 A -> B,然后從 B -> C 等等。 也許有一些包含坐標集的變量,這些變量會作為參數輸入到一些動畫函數中。 但是我嘗試的任何操作都只會導致執行最后一個命令,因此它會直接從 A -> C 移動,而忽略 B。感謝任何建議/演示。
Javascript
var canvas = new fabric.Canvas('scene', { backgroundColor: 'green'});
var triangle = new fabric.Triangle({
width: 30
, height: 30
, fill: 'red'
, left: 30
, top: 0
});
canvas.add(triangle);
function animateTop() {
triangle.animate('top', '+=55', {
duration: 1000,
onChange: canvas.renderAll.bind(canvas)
});
}
function animateLeft() {
triangle.animate('left', '+=100', {
duration: 1000,
onChange: canvas.renderAll.bind(canvas)
});
}
function fireAnimation() {
animateTop();
animateLeft();
}
document.onreadystatechange = function () {
if (document.readyState == "complete") {
fireAnimation();
}
}
HTML
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>JS Bin</title>
<script src="http://cdnjs.cloudflare.com/ajax/libs/fabric.js/1.4.0/fabric.min.js"></script>
</head>
<body>
<canvas id="scene" width="400" height="400" />
</body>
</html>
您面臨的問題是動畫函數不會相互阻塞,因此當您的fireAnimation()
函數運行時,它會同時啟動兩個動畫,並且每個動畫更改都應用於每一幀,這意味着兩者動畫同時發生。
解決此問題的一種方法是使用動畫.onComplete
事件鏈接動畫調用。 如果您需要更新動畫的順序,這樣做可能會使您陷入困境。
鑒於您提議可能有一個動畫列表來一個接一個地應用,您可以通過創建一個通用函數來更好地服務,該函數基於這樣的動畫參數輸入列表應用動畫(代碼注釋中的解釋):
function startAnimationQueue(animationQueue){
// queues up the animations for the shape
var runningDuration = 0; // variable that adds up the animationQueue durations
for (var i=0; i<animationQueue.length; i++){
var animationDefinition = animationQueue[i];
// Create a closure around the animationDefiniton so that each setTimeout gets sequential animationDefinition inputs
var fn = (function(animationDefinition){
return function(){
triangle.animate('left', animationDefinition.left, {duration: animationDefinition.duration, onChange:canvas.renderAll.bind(canvas)})
triangle.animate('top', animationDefinition.top, {duration: animationDefinition.duration, onChange:canvas.renderAll.bind(canvas)})
// Note: you can animate additional attributes here if you want, just add additional attributes to the objects in
// the animationQueue list. You could also have one of those inputs be the object to be animated in case you want
// to animate multiple objects using the same queue.
};
})
// Create the timeout that will apply the transformations sequentially
// If you want you could set the window.setTimeout to a variable that you could destroy if you need
// to interrupt the animation queue after you create it (but before it finishes)
window.setTimeout(fn(animationDefinition), runningDuration);
// set the next setTimeout duration to be .duration later than the previous one
// this makes the second animation fire after the first one completes
runningDuration += animationDefinition.duration;
}
}
document.onreadystatechange = function () {
if (document.readyState == "complete") {
// I put the canvas init stuff in here because of (I think) a failed race condition or something that caused
// your original method to fail in Chrome
window.canvas = new fabric.Canvas('scene');
window.triangle = new fabric.Triangle({
width: 30
, height: 30
, fill: 'red'
, left: 30
, top: 0
});
window.canvas.add(window.triangle);
window.canvas.renderAll();
// Create a list of animations to apply
var animationQueue = [
{"left": "+=0", "top": "+=100", "duration": 1000},
{"left": "+=55", "top": "+=0", "duration": 2000}
]
// Apply the animations in sequence using window.setTimeout
startAnimationQueue(animationQueue);
}
}
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.