Animationend Event Not Firing on :After Element

animationend event not firing

There are two separate animating events.

  1. animationend
  2. transitionend

When using the css transition use transitionend, and when using @keyframes/animation, use animationend.

Animationend event not firing on :after element

After searching the web it has become apparent that IE does not yet support the binding to animation events on a pseudo element. This is made more obvious by the jsFiddle I posted in my original post, which doesn't trigger the event when the animation ends.

animationend event also also fires on end of animations of child elements?

You can check if the event's target is the element the listener is attached to. The event handler is also called when the animation on a child element ends because the animationend event bubbles.

document.querySelector('.outer').addEventListener('animationend', function(e) {
if(e.target === this) console.log('done')
})

document.querySelector('.outer').addEventListener('animationend',function (e) {
if(e.target === this) console.log('done')
})
body {
height:100vh;
display:grid;
place-items:center;
}

.outer {
display:grid;
place-items:center;
height:200px;
width:200px;
background:black;
animation:spin 2s
}

.inner {
height:50px;
width:50px;
background:red;
animation:spin 2s 2s
}

@keyframes spin {
from {
transform:rotate(0)
}
to {
transform:rotate(360deg)
}
}
<div class="outer">
<div class="inner">

</div>
</div>

addEventListener not firing when animation ends

Put your multiple event types in an array the use .forEach() method.

SNIPPET

var div = document.querySelector('.animated');

['webkitAnimationEnd', 'animationend'].forEach(function(e) { div.addEventListener(e, eventHandler, false);});
function eventHandler(e) { var tgt = e.target; tgt.style.color = 'red';}
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/animate.css/3.5.2/animate.min.css">

<div class="animated tada">TADA!</div>

Detect element CSS animation end, child items firing the event

animationend bubbles, so animations on descendant elements bubble up to the parent.

If you only want to handle the event when it relates specifically to elm (this.$refs.container), compare event.target to elm (or event.currentTarget) and ignore the event if they don't match:

elm.addEventListener('transitionend', event => {
if (event.target !== event.currentTarget) {
return; // Ignore it
}
console.log(event.target);
});

Updated Example (I've added a border to the container so you can see the animation occur and see that the console.log happens when it ends):

Vue.component('test', {
data: function () {
return {
count: 0
}
},
methods: {
expand() {
const elm = this.$refs.container;

elm.addEventListener('transitionend', event => {
if (event.target !== event.currentTarget) {
return; // Ignore it
}
console.log(event.target);
});

elm.style.height = '100px';
}
},
template: `
<div>
<p @click="expand()">Expand</p>
<div class="container"
ref="container">
<ul>
<li>Item 1</li>
<li>Item 2</li>
<li>Item 3</li>
<li>Item 4</li>
</ul>
</div>
</div>
`
})

new Vue().$mount('#app');
.container {
transition: height .3s ease;
height: 0;
border: 1px solid grey;
}
.container ul li:hover {
background: red;
}
.container ul li {
transition: background .2s ease-in-out;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.17/vue.js"></script>
<div id="app">
<test></test>
</div>

How to fire animationend event, when I can't set a CSS animation?

You can check if element.style.WebkitAnimation and element.style.animation contain any value and execute run() if the value is ""

Edit Turns out that .style will return "" for any value. What you need is window.getComputedStyle() along with the property animationName. If it is none, there is no animation, else there is. Check the code below:

var el1 = document.getElementById("notAnimation");console.log(window.getComputedStyle(el1)["animationName"])
var el2 = document.getElementById("onAnimation");console.log(window.getComputedStyle(el2)["animationName"])
div {  padding: 10px;  margin: 20px;}
#notAnimation {}
#onAnimation { animation: scale 10s ease-in-out;}
@keyframes scale { 0% { transform: scale(1); opacity: 1; color: black; } 50% { transform: scale(0.95); opacity: .4; color: red; } 100% { transform: scale(1); opacity: 1; color: black; }}
<div id="notAnimation">  Not Animation</div>
<div id="onAnimation"> Animation</div>

JS EventListener animationend firing too early

Your issue is in your addEventListener:

element.addEventListener("webkitAnimationEnd", element.classList.remove("smoothTransition"));
element.addEventListener("animationend", element.classList.remove("smoothTransition"));

The second argument of addEventListener must be a a function and not the result of a function call (in your case undefined). Hence, change the previous lines to:

element.addEventListener("webkitAnimationEnd", function(e) {
this.classList.remove("smoothTransition")
});
element.addEventListener("animationend", function(e) {
this.classList.remove("smoothTransition")
});

You may consider to add your event listeners before transitions.

document.addEventListener("DOMContentLoaded", function(e) {  var element = document.querySelector('.box');  element.addEventListener("webkitAnimationEnd", function(e) {      this.classList.remove("smoothTransition");      console.log('webkitAnimationEnd');  });  element.addEventListener("animationend", function(e) {      this.classList.remove("smoothTransition");      console.log('animationend');  });  element.classList.add("smoothTransition")  element.classList.toggle("fullscreen")});
.box {    width: 150px;    height: 150px;    background: red;    margin-top: 20px;    margin-left: auto;    margin-right: auto;}@keyframes colorchange {    0% { background: yellow }    100% { background: blue }}.smoothTransition {    animation: colorchange 2s;}.fullscreen {    width: 100%;    height: 100vh;}
<div class="box"></div>


Related Topics



Leave a reply



Submit