I'm using Snap.svg to animate 13 SVGs. All the SVGs start from one point and animate through several other animations (through callbacks). An simplified example of my animation is described, in code, below:
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 over the array and set a timeout for the first animation like so:
people.map(function(person, index) {
setTimeout(function() {
animatePerson(person);
}, (300*index));
});
However this did not work as the SVGs would start to overlap/overtake each other when they looped. Then I tried to set the timeout equal to the length of time it took for one complete "lap" of the animation and divide that by the total amount of SVGs like so:
people.map(function(person, index) {
setTimeout(function() {
animatePerson(person);
}, (1600/people.length));
});
Is there a way in Snap.svg or JavaScript to have the animation loop using callbacks and/or timeouts, or an I way off here?
Here is an image of the full animation I am referring to:

One way I have done this, is to write a small function that takes in an element and an array of preset animations, and go through them in turn via the callback, which looks like this...
Edit: Modified slightly to be able to include a different element per animation, and example2 link below, includes the option to include a function to call each time as well.
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 could pass it an array of anims, like this...
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 run on there)
example 2 (this allows you to include a func to call as well as part of it)
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With