I have an element which is invisible at first (opacity: 0
).
When an animation is triggered, it fades in, but since the value of opacity
seems to get reset, it vanishes again after completion.
How do I prevent a reset of the animated properties?
I use animate.css 4.1.1 with Google Chrome.
Example context:
HTML:
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/animate.css/4.1.1/animate.min.css" />
<div class="main-container">
<div id="test1"></div>
</div>
CSS:
#test1 {
position: absolute;
margin: 10%;
width: 25%;
height: 25%;
opacity: 0;
background: blue;
}
The code below uses this JS function to add animation classes (found on the animate.css website):
const animateCSS = (element, animation, prefix = 'animate__') =>
// We create a Promise and return it
new Promise((resolve, reject) => {
const animationName = `${prefix}${animation}`;
const node = document.querySelector(element);
node.classList.add(`${prefix}animated`, animationName);
// When the animation ends, we clean the classes and resolve the Promise
function handleAnimationEnd(event) {
event.stopPropagation();
node.classList.remove(`${prefix}animated`, animationName);
resolve('Animation ended');
}
node.addEventListener('animationend', handleAnimationEnd, {once: true});
});
Here I try to trigger an in animation, wait for a moment and then have an out animation.
The described problem manifests as a flickering (can be seen in this jsfiddle.)
First I thought that the solution should be as easy as changing the property.
after completion:
let test1 = document.getElementById("test1");
animateCSS("#test1", "flipInX") // flickers
.then(()=>{
test1.style.opacity = 1;
});
...
animateCSS("#test1", "flipOutX")
.then(()=>{
test1.style.opacity = 0;
});
immediately:
let test1 = document.getElementById("test1");
animateCSS("#test1", "flipInX")
test1.style.opacity = 1;
...
animateCSS("#test1", "flipOutX") // flickers
test1.style.opacity = 0;
Then I thought that the flickering is caused by any animation delay.
So I disabled that:
test1.style.setProperty('--animate-delay', '0s');`
document.documentElement.style.setProperty('--animate-delay', '0s');
Without any effect.
What am I doing wrong?
UPDATE:
I ended up using a modified version of the answer:
function animateCss(node, animationName, duration = 1, prefix = 'animate__') {
const envCls = `${prefix}animated`;
const animationCls = `${prefix}${animationName}`;
// Remove all applied animate.css classes.
node.className = node.className
.split(" ")
.filter((cls) => !cls.startsWith(prefix))
.join(" ");
// Promise resolves when animation has ended.
return new Promise((resolve, reject) => {
node.addEventListener('animationend', (event) => {
event.stopPropagation();
resolve('Animation ended');
}, {once: true});
node.style.setProperty('--animate-duration', `${duration}s`);
node.classList.add(envCls, animationCls); // Starts CSS animation.
});
}
// --- Test ---
let test1 = document.getElementById("test1");
// hide the element at first.
animateCss(test1, "fadeOut", 0);
setTimeout(()=>{
animateCss(test1, "flipInX");
}, 1000);
setTimeout(()=>{
animateCss(test1, "zoomOut");
}, 5000);
Couple of issues here:
flipInX
, and flipOutX
already controls opacity. You don't have to manage it yourself.const animateCSS = (element, animation, lastAnim, prefix = 'animate__') => {
const animationName = `${prefix}${animation}`;
const node = document.querySelector(element);
// remove the last animation
node.classList.remove(`${prefix}animated`, `${prefix}${lastAnim}`);
// We create a Promise and return it
return new Promise((resolve, reject) => {
node.classList.add(`${prefix}animated`, animationName);
function handleAnimationEnd(event) {
event.stopPropagation();
//do not remove the class here
//node.classList.remove(`${prefix}animated`, animationName);
resolve('Animation ended');
}
node.addEventListener('animationend', handleAnimationEnd, { once: true});
});
}
// Test ------------------------------------------------------------
let test1 = document.getElementById("test1");
test1.style.setProperty('--animate-duration', '2s');
setTimeout(() => {
document.body.appendChild(document.createTextNode('1'));
animateCSS("#test1", "flipInX");
}, 1000);
setTimeout(() => {
document.body.appendChild(document.createTextNode('2'));
animateCSS("#test1", "flipOutX", "flipInX")
}, 3000);
setTimeout(() => {
document.body.appendChild(document.createTextNode('3'));
animateCSS("#test1", "flipInX", "flipOutX")
}, 6000);
setTimeout(() => {
document.body.appendChild(document.createTextNode('4'));
animateCSS("#test1", "flipOutX", "flipInX");
}, 9000);
#test1 {
position: absolute;
width: 25vw;
height: 25vw;
top:3rem;
left: 6rem;
background: blue;
/* starting state */
-webkit-transform: perspective(400px) rotate3d(1, 0, 0, 90deg);
transform: perspective(400px) rotate3d(1, 0, 0, 90deg);
}
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/animate.css/4.1.1/animate.min.css" />
<div class="main-container">
<div id="test1"></div>
</div>