0

I want to add and remove a CSS class n times to show an animation, to show a effect n times, like when you set animation-iteration-count, the diffence is that here I have two animations, the second with delay.

My idea was to use setTimeout, so I read this Stack Overflow post but I didn't get the expected results.

Here is a snippet - and a JSfiddle - with the animation (showing once)

$('button').click(function(){
  $('div').addClass('a');
  
  $(this).attr('disabled','true').text('Started');
  
  setTimeout(function(){
    $('div').removeClass('a');
    
    $('button').removeAttr('disabled').text('Finished | Again');
  },6000);
});
div {
  width: 100px; height: 100px; background: red;
}

.a {
  animation: a 2s linear, b 2s 2s linear;
}

@keyframes a {
  from { background: red; }
  to { background: blue; }
}

@keyframes b {
  from { background: blue; }
  to { background: black; }
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>

<div></div>
<button>Start</button>
Community
  • 1
  • 1
agustin
  • 2,187
  • 2
  • 22
  • 40
  • 1
    Can you go into more detail about what you are trying to exactly achieve? If you want a setTimeout to run multiple times (as in the other thread you linked) you have to call it recursively which you are not doing here. – Damon Mar 31 '16 at 21:45
  • Unlike `setInterval()`, `setTimeout()` will not repeat and I don't see your `setTimeout` invoking anything that would cause it run more once. – Fizz Mar 31 '16 at 21:46
  • @Damon yes, because as I said, I didn't get the expected results. I want to repeat n times a multiple animation and I don't know how to do it. I mentioned 'setTimeout' as an option. What is the best way to do that? Thanks! – agustin Mar 31 '16 at 21:49
  • Use setInterval() and clearInterval(). Basically set up a variable let's say `interval` and set it equal to your `setInterval` function. Have a counter n. After n loops of the interval, call `clearInterval(interval);` (Edit: if you need an example I'll post something in answers - let me know if that works) – Damon Mar 31 '16 at 21:52
  • @Damon Can you give an example, please? Thank you – agustin Mar 31 '16 at 22:00

4 Answers4

0

You can use setInterval and count the number of iterations.

var n = 3;
var iterationCount = 0;

$('button').click(function(){
clearInterval(animInterval);

var animInterval = setInterval(function(){
    $('div').toggleClass('a');
    iterationCount++;

    if (n == iterationCount)
        clearInterval(animInterval);
  },4000);
});

https://jsfiddle.net/brhL9h54/10/

Ryan Dantzler
  • 1,124
  • 1
  • 8
  • 18
0

the css way

Repeating an animation with js seems wrong to me. There is the animation-iteration-count property, and with the possibility off adding multiple @keyframes you should be able to achieve what you are after. For your sample code it is quite simple even (though I suspect your real animation may be a bit different:

.a {
  animation: a 2s linear 5 alternate;
}

@keyframes a {
  0% { background: red; }
  50% { background: blue; }
  100% { background: black; }
}

Feel free to post your actual animation if you can't find a way to achieve it with just css. https://jsfiddle.net/brhL9h54/4/

the js way

If you insist on going the js way, you'll need to make sure the timeout gets reset after every cycle. This can be done by using calling a function recursively. And with the help of a counter you can easily control how many times you want it to run. Something in this order:

$('button').click(function(){
  $('div').addClass('a');

  $(this).attr('disabled','true').text('Started');

  var counter = 5;

  function repeater() {
    if (counter >= 0) {
       $('div').toggleClass('a');
       counter--;
       // start new cycle
       setTimeout(repeater, 3000);
    } else {
       // cleanup
       $('button').removeAttr('disabled').text('Finished | Again');
    }
  }

  // boot the repeater
  repeater()
});

https://jsfiddle.net/brhL9h54/7/

Pevara
  • 14,242
  • 1
  • 34
  • 47
  • Thanks, but I must use multiple animations, background-color was an example – agustin Mar 31 '16 at 21:53
  • That what I meant with my final remark, "Feel free to post your actual animation". Anyways, if you insist on going the js route (which is probably not necessary), I've updated my answer with a possible solution. – Pevara Mar 31 '16 at 22:07
0

You can handle animationend event. Look at this code:

$('div').on('animationend', function (data) {
 if (data.originalEvent.animationName === 'b') {
  $('div').removeClass('a');
  iteration++;
  if (iteration < n) {
   setTimeout(function () {  $('div').addClass('a'); });
  } else {
   iteration = 0;
   $('button').removeAttr('disabled').text('Finished | Again');
  }
 }
});

There is parameter data.originalEvent.animationName which indicates animation name which is ended. Your last animation is b. So then you have to remove class and add it again. You have to also keep somewhere current iteration number and max interations. Check this on here: https://jsfiddle.net/svnwmg3g/

RobHil
  • 116
  • 1
0

Here is an update to your fiddle:

https://jsfiddle.net/jb03ba1f/2/

As you can see, this will repeat the animation however many times you want, and can also accommodate multiple animations, but it's a little messy. Since you are already using jQuery, I would suggest looking into jQuery's animate API which (I think) has more robust callbacks buuut I hardly use jQuery so you will have to look into that.

If this doesn't cover what you're looking for, maybe you can find an example online to better illustrate your question.

(js / jquery for reference - though I did also update the keyframes to add another animation so look at the fiddle)

$('button').click(function(){
    $('div').addClass('a');

  $(this).attr('disabled','true').text('Started');

  var n = 0;

  var interval = setInterval(function() {
    $('div').removeClass('a');

    if (n === 5) {
        clearInterval(interval);
        $('button').removeAttr('disabled').text('Finished | Again');
    } else {
      setTimeout(function() {
        $('div').addClass('a');
      }, 0)
      n++;
    }
  }, 4500);
});
Damon
  • 4,216
  • 2
  • 17
  • 27