Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

JavaScript detect CSS animation in progress

I'm having some trouble in my JavaScript deciding whether to wait for animationend events or not and wondered if an elegant solution to this problem exists.

Lets say that I have a div that animates on page load and fades in, then at a later time I have another script that appends an <img> tag to the div.

I want the <img> to be appended after the animation has completed in order to avoid any stuttering during the animation and to just make it look nicer.

Currently I know that I can write something like this (assuming I use animate.css):

HTML:

<div class="append-image-here animated fadeIn"></div>

JavaScript:

$(function() {
  $('.append-image-here').one([
    'webkitAnimationEnd',
    'mozAnimationEnd',
    'MSAnimationEnd',
    'oanimationend',
    'animationend'
  ].join(' '), function() {
    $('<img>', { src: '/image.jpg' }).appendTo(this);
  });
});

This is fine if the script runs before the animation completes and the animationend event fires, but if the script happens to run after the animation ends the <img> tag will never be created and will never be appended to the div (for example if the handler was set in a timeout or something like that which ran past the animation duration).

Is there any way to detect if a CSS animation is currently running so the script can decide whether to wait for the animationend or not without having to rely on user added classes or data attributes?

(I ask to not rely on classes and attributes because if I'm working with someone else's animations I may not know the classes ahead of time)

Any help would be appreciated.

like image 710
Lucas Avatar asked Oct 20 '22 08:10

Lucas


1 Answers

Why not just using .on() on the document and even check which animation has just finished and which element was animated (e.target) The event handler will attached before the DOM is fully loaded and CSS animation are fired.

DEMO: JSnippet Demo

Note: do not attach when DOM ready - $(function(){ ... })

$(document).on([
    'webkitAnimationEnd',
    'mozAnimationEnd',
    'MSAnimationEnd',
    'oanimationend',
    'animationend'
    ].join(' '), function(e) {
       //Do whatever you want 
       console.log(e);
       $('ul').append(
          "<li>Animation end detected on: "  
          + e.target 
          + "." + e.target.className + 
          "</li>"
       );
});

$(function(){
  
    $('button').click(function(){
        $(this).addClass('animate');
    });
    
});

$(document).on([
    'webkitAnimationEnd',
    'mozAnimationEnd',
    'MSAnimationEnd',
    'oanimationend',
    'animationend'
  ].join(' '), function(e) {
    //Do whatever you want 
    console.log(e);
    $('ul').append(
        "<li>Animation end detected on: "  
        + e.target 
        + "." + e.target.className + 
        "</li>"
    );
    $('button').removeClass('animate');
});
button {
        width: 300px;
        background-color: red;
}
button.animate {
        -webkit-animation-name: example; /* Chrome, Safari, Opera */
        -webkit-animation-duration: 1s; /* Chrome, Safari, Opera */
        animation-name: example;
        animation-duration: 1s;
}
/* Chrome, Safari, Opera */
@-webkit-keyframes example {
    from {background-color: red;}
    to {background-color: yellow;}
}

/* Standard syntax */
@keyframes example {
    from {background-color: red;}
    to {background-color: yellow;}
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
<button class="animate">Trigger animation</button>
<ul></ul>
like image 61
Shlomi Hassid Avatar answered Oct 22 '22 00:10

Shlomi Hassid