Aritra Hazra
Aritra Hazra

Reputation: 65

Detecting "animationend" event of a chained animation set

This is my CSS, in which, three keyframes are bound together to make a chain animation

#anim-div{
    -webkit-animation-name    : mpbar-anim-page1, mpbar-anim-page2, mpbar-anim-page3;
    animation-name            : mpbar-anim-page1, mpbar-anim-page2, mpbar-anim-page3;
    -webkit-animation-delay   : 0s, 0.7s, 1.4s;
    animation-delay           : 0s, 0.7s, 1.4s;
    -webkit-animation-duration: 0.7s;
    animation-duration        : 0.7s;
}

Is it possible to detect animationend event of the whole set?
when I try, it detects animationend for each individual keyframes (ending up firing 3 events)

Upvotes: 2

Views: 1115

Answers (2)

Shaggy
Shaggy

Reputation: 6796

Assuming that the number of animations is unknown and the name of the final animation is also unknown, you could achieve this by using getComputedStyle to read the animations into an array. Then, when the animationend event fires, increment a variable and execute the code you wish when the value of that variable equals the length of the array, like so:

var div=document.querySelector("div"),
    style=window.getComputedStyle(div),
    animation=style.getPropertyValue("animation-name")||style.getPropertyValue("-moz-animation-name")||style.getPropertyValue("-webkit-animation-name"),
//  Delete unneeded prefixed properties above 
    count=animation?animation.split(",").length:0,
    ended=0;
div.addEventListener("animationend",function(){
  ended++;
  if(ended===count){
//  Your code here
    console.log(ended+" animations completed.");
  }
},0);
div{
  animation:x 1s ease-in-out,y 1s ease-in-out 1s,z 1s ease-in-out 2s;
  background:#000;
  height:50px;
  width:50px;
}
@keyframes x{to{transform:rotatex(180deg);}}
@keyframes y{to{transform:rotatey(180deg);}}
@keyframes z{to{transform:rotatez(180deg);}}
/* Housekeeping */
body,html{height:100%;}
body{align-items:center;display:flex;justify-content:center;}
<div></div>

Upvotes: 3

andreivictor
andreivictor

Reputation: 8461

We can assume that the animationend event of the whole set is actually the animationend event of the animation that ends last (in our case, the third animation).

So in the animationend event that is binded to our element, we need to detect the name of the animation that has just ended and check if it matches the third animation. We can acces the originalEvent object and get the animationName property.

Try the following code:

$(document).ready(function(){

    $('#anim-div').on(animationEvent, function(e){
         var animationName = e.originalEvent.animationName;
         if (animationName == 'mpbar-anim-page3') {
             console.log('"' + animationName + '" animation has finished');
        }
    });

});

I've used the variable animationEvent to get the correct name of the animationend event (some browsers may require a prefixed version). You need to put the folllowing code before the one above:

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();

I've also put the complete code in a fiddle: https://jsfiddle.net/psxxbp2y/.

Tested in Firefox, Chrome and Opera.

Upvotes: 3

Related Questions