JavaScript animation: handling complex animations using callbacks and a loop

I am using Snap.svg for 13 SVG animations. All SVGs start at one point and animate several other animations (via callbacks). Below is a simplified example of my animation:

var reset = function(person) {
    person.attr({transform: 't0,0', opacity: 0});
    animatePerson(person);
};

var animatePerson = function(person) {
    person.animate({opacity: 1}, 300, null,function() {
        person.animate({transform: 't100,20'}, 1000, null, function() {
            person.animate({opacity: 0}, 300, null, function() {
                reset(person);
            });
        });
    });
};

var people = [Snap('#Person_1'), Snap('#Person_2'), Snap('#Person_3'), Snap('#Person_4'), Snap('#Person_5')];

      

My first attempt was to map an array and set a timeout for the first animation like this:

people.map(function(person, index) {
    setTimeout(function() {
        animatePerson(person);
    }, (300*index));
});

      

However, this didn't work as the SVGs will start to overlap / overlap each other as they loop. Then I tried to set the timeout equal to the length of time it took for one full "circle" of animation, and divided by the total number of SVGs:

people.map(function(person, index) {
    setTimeout(function() {
        animatePerson(person);
    }, (1600/people.length));
});

      

Is there a way in Snap.svg or JavaScript to have an animation loop using callbacks and / or timeouts, or is this where I am here?

Here is a picture of the complete animation I'm talking about:

enter image description here

+3


source to share


1 answer


One way I've done this is to write a small function that takes an element and an array of preset animations, and in turn through them via a callback that looks like this ...

Edit: slightly modified to include a different element on the animation and the example2 link below includes the ability to enable a function to be called each time.

function nextFrame ( frameArray,  whichFrame ) {
    if( whichFrame >= frameArray.length ) { return }
    frameArray[ whichFrame ].el.animate(    
          frameArray[ whichFrame ].animation,
          frameArray[ whichFrame ].dur,
          frameArray[ whichFrame ].easing,
          nextFrame.bind(null,  frameArray, whichFrame + 1 )
    );
}

      

Then you can pass it an array of animations like ...

var myFrames = [
    {   el: g,  animation: { transform: 'r360,150,150' }, dur: 1000, easing: mina.bounce },
    {   el: r,  animation: { transform: 't100,-100s2,3' }, dur: 1000, easing: mina.bounce },
    {   el: r,  animation: { transform: 't100,100' }, dur: 1000, easing: mina.bounce },
    {   el: g,  animation: { transform: 's2,1' }, dur: 1000, easing: mina.bounce },
    {   el: r,  animation: { transform: 's1,2' }, dur: 1000, easing: mina.bounce },
    {   el: c,  animation: { transform: 's1,1' }, dur: 1000, easing: mina.bounce }];

      



Then you can call it with

nextFrame( el, myFrames, 0 );

      

example (click here).

example 2 (this allows you to include func for the call as well as part of it)

+2


source







All Articles