简体   繁体   中英

jQuery + Animate.css animation only working once, animation not resetting

I'm trying to reproduce a specific animation each time a button is pressed.

Specifically, I'm using jQuery and the animate.css library for this effect: on button click, a class is added (two classes to be precise: fadeInDown animated ) to the element I want to animate.

The animation does work correctly, but only once. Why is this?

Fiddle: http://jsfiddle.net/jqm4vjLj/2/

I want the animation to reset every time I click the button, even if it is halfway through completion from a previous click. It should also work whenever I click the button, not only once.

JS:

$("#button").click(function () {
    $("#button").removeClass();
    $("#button").addClass("fadeInDown animated");
});

Classes from animate.css:

@-webkit-keyframes fadeInDown {
  0% {
    opacity: 0;
    -webkit-transform: translateY(-20px);
    transform: translateY(-20px);
  }

  100% {
    opacity: 1;
    -webkit-transform: translateY(0);
    transform: translateY(0);
  }
}

@keyframes fadeInDown {
  0% {
    opacity: 0;
    -webkit-transform: translateY(-20px);
    -ms-transform: translateY(-20px);
    transform: translateY(-20px);
  }

  100% {
    opacity: 1;
    -webkit-transform: translateY(0);
    -ms-transform: translateY(0);
    transform: translateY(0);
  }
}

.fadeInDown {
  -webkit-animation-name: fadeInDown;
  animation-name: fadeInDown;
}

.animated {
  -webkit-animation-duration: 1s;
  animation-duration: 1s;
  -webkit-animation-fill-mode: both;
  animation-fill-mode: both;
}

A much safer approach will be use the animation end event like

 $("#button").click(function() { $("#button").addClass("fadeInDown animated").one('animationend webkitAnimationEnd oAnimationEnd', function() { $("#button").removeClass(); }); });
 #button { height: 30px; width: 120px; border: 1px solid black; } .animated { -webkit-animation-duration: 1s; animation-duration: 1s; } @-webkit-keyframes fadeInDown { 0% { opacity: 0; -webkit-transform: translateY(-20px); transform: translateY(-20px); } 100% { opacity: 1; -webkit-transform: translateY(0); transform: translateY(0); } } @keyframes fadeInDown { 0% { opacity: 0; -webkit-transform: translateY(-20px); -ms-transform: translateY(-20px); transform: translateY(-20px); } 100% { opacity: 1; -webkit-transform: translateY(0); -ms-transform: translateY(0); transform: translateY(0); } } .fadeInDown { -webkit-animation-name: fadeInDown; animation-name: fadeInDown; }
 <script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script> <div id="button"></div>

See http://css-tricks.com/restart-css-animation/ , which discusses this exact problem.

I think the cleanest solution is to wrap the functionality of removing the element and re-inserting it in the same position in the HTML tree in a global function. Then, when you want to restart an animation, you just remove the class, call the reset function (grabbing the newly-inserted element from the return value), and then add the animation class(es) back to start the animation again.

For example:

function reset($elem) {
    $elem.before($elem.clone(true));
    var $newElem = $elem.prev();
    $elem.remove();
    return $newElem;
} // end reset()

$("#button").click(function () {
    var $this = $(this);
    $this.removeClass();
    $this = reset($this);
    $this.addClass("fadeInDown animated");
});

http://jsfiddle.net/jqm4vjLj/6/

This solution provides maximum responsiveness, since the old in-progress animation is automatically ended when the animating element is destroyed, and the newly-inserted element's animation begins immediately.

The simple solution for me is to start reflow process before adding class. You can do it for example by "change" width of element. I think reflow process is faster for browser then node reinserting. And its simpler in terms of coding. In jQuery:

$(this)
  .removeClass('myAnimation')
  .width('auto') // the magic
  .addClass('myAnimation')

You need to remove class after the animation is complete,

but directly using removeClass wont work, because it will not let animation complete, instead use setTimeout

see this http://jsfiddle.net/jqm4vjLj/4/

   $("#button").click(function () {

        $("#button").addClass("fadeInDown animated");
        setTimeout(function(){ $("#button").removeClass("fadeInDown animated");},100)
    });

Problem is it immediately remove class and then add class so I just added new div with button2 id and on its click it just remove class and then click again on button div it would animate.

so problem is you need to do it after completion of animation.

$("#button1").click(function () {
    $("#button").removeClass();
});

fiddle is here: http://jsfiddle.net/jqm4vjLj/5/

maybe this is good solution for your problem:

https://jsfiddle.net/d2c16fk7/3/

In your javascript the classes .animation and .fadeInDown were added to the #button and after that you had these classes and you couldn't add it again.

This works for me, from the animate.css github:

animateCss: function (animationName) {
    var animationEnd = 'webkitAnimationEnd mozAnimationEnd MSAnimationEnd oanimationend animationend';
    $(this).addClass('animated ' + animationName).one(animationEnd, function() {
        $(this).removeClass('animated ' + animationName);
    });
}

To reset the element we have to make css recalculate right ? So what I did was hide and then show the element. What I did was removeClass() and then hide() and then show() and addClass()

$("#button").click(function () {
    $("#button").removeClass("fadeInDown animated").hide();
    $("#button").show().addClass("fadeInDown animated");
});

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM