簡體   English   中英

Fabric.js 動畫對象/圖像

[英]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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM