user5887516
user5887516

Reputation: 81

Detecting a specific CSS keyframe animation with JQuery event

I have two CSS @keyframe animations applied to the same element. One that fires on :hover and the other that fires on mouse out, both applied with CSS.

I was curious to know if there was a way to detect the end of a selected keyframe animation rather than it being attached to the element and firing twice?

Upvotes: 8

Views: 4233

Answers (2)

Harry
Harry

Reputation: 89760

if there was a way to detect the end of a selected keyframe animation

If your intention is to detect the ending of a keyframe animation itself instead of detect end of every keyframe then, yes, it can be done using the animationend event. This event is fired every time any animation that is attached to the element is completed and the context info has one parameter named animationName using which we can find which animation had ended.

The animationName parameter is important because when multiple animations would be applied to the same element like in your case then you'd need to know which animation had actually ended because this event would get fired at the end of every animation.

Using vanilla JS:

window.onload = function() {
  var elm = document.querySelector('.animate');
  var op = document.querySelector('.output');

  elm.addEventListener('animationend', function(e) { /* this is fired at end of animation */
    op.textcontent = 'Animation ' + e.animationName + ' has ended';
  });
  elm.addEventListener('animationstart', function(e) { /* this is fired at start of animation */
    op.textcontent = 'Animation ' + e.animationName + ' has started';
  });
}
.animate {
  height: 100px;
  width: 100px;
  margin: 10px;
  border: 1px solid red;
  animation: shake-up-down 2s ease;
}
.animate:hover {
  animation: shake-left-right 2s ease forwards;
}
@keyframes shake-up-down {
  0% {
    transform: translateY(0px);
  }
  25% {
    transform: translateY(10px);
  }
  75% {
    transform: translateY(-10px);
  }  
  100% {
    transform: translateY(0px);
  }  
}
@keyframes shake-left-right {
  0% {
    transform: translateX(0px);
  }
  25% {
    transform: translateX(10px);
  }
  75% {
    transform: translateX(-10px);
  }  
  100% {
    transform: translateX(0px);
  }  
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/prefixfree/1.0.7/prefixfree.min.js"></script>
<div class='animate'></div>

<div class='output'></div>


Using jQuery:

$(document).ready(function() {
  var elm = $('.animate');
  var op = $('.output');

  elm.on('animationend', function(e) { /* fired at the end of animation */
    op.html('Animation ' + e.originalEvent.animationName + ' has ended');
  });
  elm.on('animationstart', function(e) { /* fired at the start of animation */
    op.html('Animation ' + e.originalEvent.animationName + ' has started');
  });  
});
.animate {
  height: 100px;
  width: 100px;
  margin: 10px;
  border: 1px solid red;
  animation: shake-up-down 2s ease;
}
.animate:hover {
  animation: shake-left-right 2s ease forwards;
}
@keyframes shake-up-down {
  0% {
    transform: translateY(0px);
  }
  25% {
    transform: translateY(10px);
  }
  75% {
    transform: translateY(-10px);
  }
  100% {
    transform: translateY(0px);
  }
}
@keyframes shake-left-right {
  0% {
    transform: translateX(0px);
  }
  25% {
    transform: translateX(10px);
  }
  75% {
    transform: translateX(-10px);
  }
  100% {
    transform: translateX(0px);
  }
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/prefixfree/1.0.7/prefixfree.min.js"></script>
<div class='animate'></div>

<div class='output'></div>

In the above snippet, you can see how the .output div's content indicates the name of the animation that is ended after each animation completes.

Note: CSS animations still need vendor prefixes in some browsers/versions. To be on the safer side, you need to listen for the prefixed versions of the animationend event also.

Upvotes: 9

Sumanta736
Sumanta736

Reputation: 705

Try this example:

function whichAnimationEvent(){
  var t,
  el = document.createElement("fakeelement");

 var animations = {
   "animation"      : "animationend",
   "OAnimation"     : "oAnimationEnd",
   "MozAnimation"   : "animationend",
   "WebkitAnimation": "webkitAnimationEnd"
 }

for (t in animations){
  if (el.style[t] !== undefined){
    return animations[t];
  }
 }
}

var animationEvent = whichAnimationEvent();

$(".button").click(function(){
$(this).addClass("animate");
$(this).one(animationEvent,
          function(event) {
  // Do something when the animation ends
 });
});

Upvotes: 1

Related Questions