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:
source to share
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)
source to share