简体   繁体   English

Fabric.js 动画对象/图像

[英]Fabric.js animate object/image

Hello everyone this is code that ive been working with.大家好,这是我一直在使用的代码。 It moves an object from A to B. What i am trying to do is have multiple points to which it would move.它将一个对象从 A 移动到 B。我想要做的是让它移动到多个点。 So from starting position A -> B, then from B -> C and so on.所以从起始位置 A -> B,然后从 B -> C 等等。 Maybe have some variable which would contain sets of coordinates, which would get fed into some animate function as parameters.也许有一些包含坐标集的变量,这些变量会作为参数输入到一些动画函数中。 But anything i tried resulted only in executing the last command, so it would move straight from A -> C, ignoring B. Any advice/demo appreciated.但是我尝试的任何操作都只会导致执行最后一个命令,因此它会直接从 A -> C 移动,而忽略 B。感谢任何建议/演示。

Javascript 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 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>

The problem you're facing is that the animation functions don't block each other, so when your fireAnimation() function runs, it's starting both animations at the same time, and each animation change is applied on each frame, which means that both animations occur simultaneously.您面临的问题是动画函数不会相互阻塞,因此当您的fireAnimation()函数运行时,它会同时启动两个动画,并且每个动画更改都应用于每一帧,这意味着两者动画同时发生。

One way to resolve this would be to chain the animation calls using the animation .onComplete event.解决此问题的一种方法是使用动画.onComplete事件链接动画调用。 Doing this might lock you into a bit of a hellish situation if you need to update the order of your animations.如果您需要更新动画的顺序,这样做可能会使您陷入困境。

Given that you proposed perhaps having a list of animations to apply one after another you may be served better by creating a generic function that applies animations based on an input list of animation parameters like this (explanation in comments in code):鉴于您提议可能有一个动画列表来一个接一个地应用,您可以通过创建一个通用函数来更好地服务,该函数基于这样的动画参数输入列表应用动画(代码注释中的解释):

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