Bao Pham
Bao Pham

Reputation: 43

Check if element has animation-name attached by jquery?

I'd like to make something like this.

CSS library Animate.css

@keyframes fadeInUp {
  from {
    opacity: 0;
    -webkit-transform: translate3d(0, 100%, 0);
    transform: translate3d(0, 100%, 0);
  }

  to {
    opacity: 1;
    -webkit-transform: translate3d(0, 0, 0);
    transform: translate3d(0, 0, 0);
  }
}
.animate__fadeInUp {
  -webkit-animation-name: fadeInUp;
  animation-name: fadeInUp;
}
.animate__animated {
  animation-duration: 1s;
  animation-fill-mode: both;
}

HTML

<div class="animatedScroll animate__animated animate__fadeInUp" style="animation-delay: 0.3s;"><p>111</p></div>
<div class="animatedScroll"><p>222</p></div>

jQuery

$(function(){
    var element = $('.animatedScroll');
    $.each(element, function(i){
        let ele = $(this);
        var hasAnimation = false;
        var name = '';

        $(this).on('animationstart', function(e){
            // If the element has an animation and it's start running
            hasAnimation = true;
            name = e.originalEvent.animationName;
        });

        if ( hasAnimation === true ) {
            console.log('animation name is : ' + name);
        }
        else {
            console.log('no animation');
        }
    });
})

I'm expecting the console log is animation name is : fadeInUp and no animation.

But the result is no animation for both element.

As far as i know it's because event animationstart fire off late.

Is there any other way to achive same goal? And can this be solve with deferred object?

Upvotes: 3

Views: 142

Answers (1)

Carsten Massmann
Carsten Massmann

Reputation: 28196

I tidied up ypur code a little bit. Your console.log() for the animation was executed immediately after you define the action for the "animationstart" event. That is much before the actual animation starts. Therefore the result was always: "no animation". Following @Ikik's advice I now introduced a "reporting function" that gives you a report about the current state of the system. I trigger the report once before the animation and once after (inside the event function).

The other thing I changed is that I associated the animation information directly with the DOM element by using its data attribute. These attributes can be accessed from JavaScript through the .dataset property.

var as=$('.animatedScroll');
as.each(function(i,ele){
  ele.hasAnimation=false;
  ele.name='';
  $(ele).on('animationstart', function(e){
    // If the element has an animation and it's start running
    ele.dataset.hasAnimation=true;
    ele.dataset.name = e.originalEvent.animationName;
    animationReport(as); // report after animation
  });
});

animationReport(as); // report before animation
  
function animationReport(sel){ // reports the most recent animation for each
  sel.each(function(i,ele){    // DOM element found in the given jQuery object sel
    console.log(ele.textContent+' has '+(ele.dataset.name||'no animation'))
  })
}
$('button').click(function(){animationReport(as)});
@keyframes fadeInUp {
  from {
    opacity: 0;
    -webkit-transform: translate3d(0, 100%, 0);
    transform: translate3d(0, 100%, 0);
  }

  to {
    opacity: 1;
    -webkit-transform: translate3d(0, 0, 0);
    transform: translate3d(0, 0, 0);
  }
}
.animate__fadeInUp {
  -webkit-animation-name: fadeInUp;
  animation-name: fadeInUp;
}
.animate__animated {
  animation-duration: 1s;
  animation-fill-mode: both;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>

<div class="animatedScroll animate__animated animate__fadeInUp" style="animation-delay: 0.3s;"><p>111</p></div>
<div class="animatedScroll"><p>222</p></div>
<button> report again </button>

Upvotes: 2

Related Questions