JavaScript animation loop not functioning as expected

I’m having trouble with a JavaScript animation loop. I’m using Raphael.js to create an explosion effect when a button is clicked. The initial animation works fine, but the loop I’ve set up to repeat the animation isn’t doing anything.

Here’s what I’m trying to do:

  1. Show an explosion shape
  2. Animate it to expand
  3. Loop between two states (expanded and original) a few times

I’ve tried two approaches:

  1. Using functions for each animation state:
function boom1() {
  star.animate({path: 'M 250,350 l 20,60 l 50,-20...', fill: 'red'}, 100, 'linear');
}

function boom2() {
  star.animate({path: 'M 250,330 l 10,80 l 70,-20...', fill: 'orange'}, 100, 'linear');
}

button.click(function() {
  star.show();
  star.animate({path: 'M 250,330 l 10,80 l 70,-20...', fill: 'orange'}, 100, 'linear');

  for(var i = 0; i < 4; i++) {
    if (i % 2 === 0) {
      boom1();
    } else {
      boom2();
    }
  }
});
  1. Putting animations directly in the loop:
button.click(function() {
  star.show();
  star.animate({path: 'M 250,330 l 10,80 l 70,-20...', fill: 'orange'}, 100, 'linear');

  for(var i = 0; i < 5; i++) {
    if (i % 2 === 0) {
      star.animate({path: 'M 250,350 l 20,60 l 50,-20...', fill: 'red'}, 100, 'linear');
    } else {
      star.animate({path: 'M 250,330 l 10,80 l 70,-20...', fill: 'orange'}, 100, 'linear');
    }
  }
});

Neither approach is working. The initial animation plays, but the loop doesn’t seem to run at all. Any ideas on what I’m doing wrong?

The issue you’re encountering is likely due to the synchronous nature of JavaScript loops. Animations in Raphael.js are asynchronous, but your loop is executing all iterations immediately without waiting for each animation to complete.

To achieve the desired effect, you should use a recursive function with setTimeout or setInterval. This approach allows each animation to finish before starting the next one. Here’s an example of how you could modify your code:

function animateExplosion(count) {
  if (count >= 8) return; // Stop after 4 cycles (8 animations)
  
  var path = count % 2 === 0 
    ? 'M 250,350 l 20,60 l 50,-20...' 
    : 'M 250,330 l 10,80 l 70,-20...';
  var fill = count % 2 === 0 ? 'red' : 'orange';
  
  star.animate({path: path, fill: fill}, 100, 'linear', function() {
    setTimeout(function() {
      animateExplosion(count + 1);
    }, 100);
  });
}

button.click(function() {
  star.show();
  animateExplosion(0);
});

This recursive approach should solve your looping issue and create the repeating explosion effect you’re after.

I’ve encountered similar issues with animation loops before. The problem lies in how JavaScript handles asynchronous operations. Your loop is running through all iterations instantly, not waiting for each animation to complete.

Here’s a trick I’ve used that works well:

function animateLoop(iterations) {
  let i = 0;
  function animate() {
    if (i >= iterations) return;
    
    let isEven = i % 2 === 0;
    let path = isEven ? 'M 250,350 l 20,60 l 50,-20...' : 'M 250,330 l 10,80 l 70,-20...';
    let fill = isEven ? 'red' : 'orange';
    
    star.animate({path: path, fill: fill}, 100, 'linear', function() {
      i++;
      setTimeout(animate, 100);
    });
  }
  
  animate();
}

button.click(function() {
  star.show();
  animateLoop(8);  // Run 4 cycles (8 animations)
});

This approach uses a closure to maintain the iteration count and recursively calls itself after each animation completes. It’s been reliable in my projects and should solve your looping issue.

hey man, ur problem is prolly cuz the animations are async but ur loop is sync. try using setTimeout or setInterval to make each animation wait for the previous one to finish. something like this:

function animate(i) {
  if (i >= 8) return;
  star.animate({...}, 100, 'linear', function() {
    setTimeout(() => animate(i + 1), 100);
  });
}

button.click(() => {
  star.show();
  animate(0);
});

this shud work better for ya