Add animation between two objects in Fabric js

2019-04-29 23:16发布

问题:

I have a very basic application that let's you create shapes and connect them with a line. To do that you would do the following.

Example

1. Click new animation
2. add rectangle
3. add child
4. add circle

You can move the shapes around , drag, and resize. I was wondering if it is possible to add a animation between two objects. So for example a small round circle ball would animate on the line between two objects. I have checked out demos on animation page in fabric js but not sure if it is possible to do from object b.

Here is the FIDDLE.

回答1:

I don't know if you can use the built in animation function in fabric because as you say these objects might be moving around themselves. But you can make something like this quite easily manually using a bit of Math:

You could do this by treating it like a wave oscillating between 0 and 1. The correct formula for this function is:

  • When the "angle" is 0, or a multiple of 2π the amplitude is 0, so the ball is at object1's center
  • When the "angle" is a multiple of π, the amplitude is 1 and the ball is at object2's center
  • When the amplitude is 0.5, the ball is in between the two objects

You can just increase the angle based on the time, on whatever period, or duration you want.

var animateBallBetweenObjects = function (obj1, obj2) {

    // Add the "ball"

    var circle = new fabric.Circle({
        radius: 10,
        fill: 'blue',
        left: obj1.getCenterPoint().x,
        top: obj1.getCenterPoint().y,
        originX: 'center',
        originY: 'middle',
        selectable: false
    });

    canvas.add(circle);

    var period = 1000;
    var amplitude = 0;
    var angle = 0;
    var prevTime = Date.now();

    var loop = function () {

        // Calculate the new amplitude

        var now = Date.now();
        var elapsed = now - prevTime;
        prevTime = now;
        angle += Math.PI * (elapsed / (period * 0.5));
        amplitude = 0.5 * (Math.sin(angle - (0.5 * Math.PI)) + 1);

        // Set the new position

        var obj1Center = obj1.getCenterPoint();
        var obj2Center = obj2.getCenterPoint();

        circle.setLeft(obj1Center.x + (amplitude * (obj2Center.x - obj1Center.x)));
        circle.setTop(obj1Center.y + (amplitude * (obj2Center.y - obj1Center.y)));
        canvas.renderAll();

        requestAnimationFrame(loop);
    }

    // Animate as fast as possible

    requestAnimationFrame(loop);
};

FIDDLE with it here.