Search code examples
animationpositionsequencecytoscape.js

Cytoscape.js animation sequence


I am trying to use cytoscape.js animations to visualise how nodes are inserted into a specific type of tree. I need to run many different animations including manipulating with position of the nodes in a sequence. When I tried to run them using delay, it didn't work - they didn't go in a sequence, so I am creating animations, pushing them into an array like this(this is an example, I have different kinds of animations):

animationArray.push(cy.nodes("[id='" + node.key + "']").animation({
        position: { x: current.x + 50, y: current.y + 50 },
        easing : easing,
        duration: duration,
        complete: function(){}
    }));

and then playing them all using a function that goes through the array - this way, they run in a sequence:

playAnimation(animationArray, 0);

function playAnimation(aniArray, i) {
    if (i === aniArray.length) {
        return;
    }
    aniArray[i].play().promise().then(function () {
        playAnimation(aniArray, i + 1)
    })
}

Note: I believe there must be better way to run animations in sequence but this is the best I got.

My problem is that when I change a position of a node in one of the animations, it doesn't stay in its new position and returns back to where it was at the beginning. For example, the node is on position A. In first animation I move it from A to position B and in second animation I want to move it from B to C. But after the first animation, the node is back to A, so it moves from A to C instead. I tried to solve it by setting node's position to B in that complete: function(){} but it didn't work as expected. It looked like all of those complete functions got executed at the same time, not in order with my animation sequence.

Any advice how should I approach this?


Solution

  • I figured it out. I guess that while pushing animation into an array, it is being initialized with current information about the nodes, and animations executed after that doesn't make effect on it. So when pushing second animation, which should move node to C, it looks at node and finds out its position, which is still A, because first animation didn't run yet. So I added something like:

    cy.$('#' + x.key).position({
            x: current.x + 50,
            y: current.y + 50
        });
    

    after pushing animation into an array. In the end, I set x position back to the beginning position and then I run animation array.