Question

I have an animation using Animate.CSS that I would like to have replay if the user would like but what I have attempted does not work. Here is the code:

HTML:

    <div class="img-center">
       <img src="path.jpg" class="feature-image animated rotateInDownRight" />
    </div>
       <p class="textcenter">&nbsp;</p>
    <div class="img-center">
       <a href="#" id="replay">Replay</a>
    </div>

JS:

var $j = jQuery.noConflict();
$j("#replay").click(function() {
    $j('.feature-image').removeClass('animated rotateInDownRight').addClass('animated rotateInDownRight');
});

I do know the script itself works as I can see it happen in Firebug however that animation doesn't animate again. How do I achieve this with Animate.CSS?

Was it helpful?

Solution

This is just a guess but it appears that jQuery isn't "finished" removing the class before it adds it back in. I know this makes NO sense, but it's how JavaScript works. It can call the next function in the chain before all the stuff from the first one is finished. I poked around the code on Animate.CSS's site and saw that they use a timeout in their animation function. You might try the same. Here's their code:

function testAnim(x) {
    $('#animateTest').removeClass().addClass(x);
    var wait = window.setTimeout( function(){
        $('#animateTest').removeClass()},
        1300
    );
}

What this is doing is exactly like what you are doing except that it waits for the animation to finish, then removes the classes. That way when the other class is added back in, it is truely "new" to the tag. Here is a slightly modified function:

function testAnim(elementId, animClasses) {
    $(elementId).addClass(animClasses);
    var wait = window.setTimeout( function(){
        $(elementId).removeClass(animClasses)},
        1300
    );
}

Notice two things: First this code would allow you to change what element gets the animation. Second, you remove the classes you added after 1300 milliseconds. Still not 100% there, but it might get you further down the road.

It should be noted that if there is already some animation classes on the object it might break this JS.

OTHER TIPS

found the right answer at animate.css issue#3

var $at = $('#animateTest').removeClass();  
//timeout is important !!
setTimeout(function(){ 
   $at.addClass('flash') 
}, 10);

Actually a simpler version can avoid using JQuery too.

el.classList.remove('animated','flash');  
//timeout is important !!
setTimeout(function(){ 
   el.classList.add('animated','flash');
}, 10);

I believe the issue here is that when I remove the class it was adding the class to quickly. Here is how I solved this issue:

(HTML is same as above question).

JS:

var $j = jQuery.noConflict();

window.setTimeout( function(){
   $j('.feature-image').removeClass('animated rotateInDownRight')},
1300);


$j("#replay").click(function() {
    $j('.feature-image').addClass('animated rotateInDownRight');
});

What I believe is happening is the jQuery code is removing and adding the class to quickly. Regardless of the reason this code works.

If you wish you can also give a try to this javaScript side development that support animate.css animations. Here is an example of usage.

 //Select the elements to animate and enjoy!
 var elt = document.querySelector("#notification") ;
 iJS.animate(elt, "shake") ;
 //it return an AnimationPlayer object
 //animation iteration and duration can also be indicated.
 var vivifyElt = iJS.animate(elt, "bounce", 3, 500) ;
 vivifyElt.onfinish = function(e) {
     //doSomething ...;
 }
 // less than 1500ms later...changed mind!
 vivifyElt.cancel();

Take a look here

My answer is a trick to add/remove the css class with a tint delay:

$('#Box').removeClass('animated').hide().delay(1).queue(function() { 
        $(this).addClass('animated').show().dequeue();
});

Also you can test it without hide/show methods:

$('#Box').removeClass('animated').delay(1).queue(function() { 
        $(this).addClass('animated').dequeue();
});

I fill it works smooth in chrome but it works with more unexpected delay in FF, so you can test this js timeout:

$('#Box').removeClass('animated');  
setTimeout(function(){ 
    $('#Box').addClass('animated');
}, 1);

This solution relies on React useEffect, and it's rather clean, as it avoids manipulating the class names directly.

It doesn't really answers the OP question (which seems to be using jQuery), but it might still be useful to many people using React and Animate CSS library.

  const [repeatAnimation, setRepeatAnimation] = useState<boolean>(true);

  /**
   * When the displayedFrom changes, replay the animations of the component.
   * It toggles the CSS classes injected in the component to force replaying the animations.
   * Uses a short timeout that isn't noticeable to the human eye, but is necessary for the toggle to work properly.
   */
  useEffect(() => {
    setRepeatAnimation(false);
    setTimeout(() => setRepeatAnimation(true), 100);
  }, [displayedFrom]);

  return (
    <div
      className={classnames('block-picker-menu', {
        'animate__animated': repeatAnimation,
        'animate__pulse': repeatAnimation,
      })}
  ...
  )
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top