Why animation play state is always running? - javascript

I couldn't get the animation play state to be paused with css3 animation even after using animation-iteration-count to 1 and animation-fill-mode to forwards:
var isRunning = window.getComputedStyle(
document.querySelector('div')
).getPropertyValue('animation-play-state');
setInterval(function(){
console.log(isRunning);
},1000)
#keyframes foo {
0% {
width: 0;
}
100% {
width: 50%;
}
}
div {
animation: foo 2s linear 0s 1 normal forwards;
background-color: #f00;
height: 3px;
}
<div></div>
I should get animation-play-state to be paused when it finishes the animation.
Actually, the following answer that I provided doesn't work for me. In fact, I was working with a pseudo element and pseudo element doesn't accept addEventListener. So, my final solution would be to use this only way.
var isRunning = window.getComputedStyle(
document.querySelector('div'), ':after'
).getPropertyValue('animation-play-state');
Sadly, CSS doesn't seem to set play state to paused when animation is finished. To conclude this question has no findings or solution?

The value of animation-play-state doesn't change once an animation finishes all its iterations.
You'll need to listen for the animationend event and change the value manually:
document.querySelector('div').addEventListener('animationend', function() {
this.style.animationPlayState = 'paused';
console.log(window.getComputedStyle(this).getPropertyValue('animation-play-state'));
});
#keyframes foo {
0% {
width: 0;
}
100% {
width: 50%;
}
}
#foo {
animation: foo 2s linear 0s 1 normal forwards;
background-color: #f00;
height: 3px;
}
<div id=foo></div>
... though I don't really see any reason to do so when your animation-fill-mode is already set to forwards.

I don't know why css3 keeps animation play state to running but go with the animationend event:
var x = document.getElementById("myDIV");
x.addEventListener("animationend", function(){
console.log('paused'); // animation is end
});
Here's the reference for animationend: https://developer.mozilla.org/en-US/docs/Web/Events/animationend

Related

Add an addEventListner on a class remove

I made some fandeIn and fadeOut codes to an exercise.
I'm trying to remove the setTimeout() on the fadeIn().
Like using an addEventListner maybe, but there is no transition on .displayNone.
On the MDN I just found transitions interacting with EventListner.
function fadeOut(disable) {
disable.classList.remove('visible');
disable.classList.add('hidden');
disable.addEventListener('transitionend', () => disable.classList.add('displayNone'));
};
function fadein(enable, timer) {
if (!timer) timer = 350;
enable.classList.remove('displayNone');
setTimeout(function () {
enable.classList.remove('hidden');
enable.classList.add('visible');
}, timer);
};
.displayNone {
display: none;
}
.visible {
visibility: visible;
opacity: 1;
transition: opacity 1.5s linear;
}
.hidden {
visibility: hidden;
opacity: 0;
transition: visibility 0s 350ms, opacity 350ms, display 350ms linear;
}
P.S.: This works good, I'm just trying another way to make it works too.
The setTimeout method returns a timeout descriptor/id (actually just an integer). You may use it to remove the timeout later:
// setting timeout
var timeout = window.setTimeout(function(){}, 5000);
window.clearTimeout( timeout )

Add css keyframe animation every image switch

I have an image tag where in every 3 seconds it changes to a different image and I want to add into it an animation style where every time the image switch, a css animation keyframe will take effect. It seems that I cant figure out how to apply the animation in javascript. Here's what Ive tried so far:
My javascript,:
let indexObj = {
imageChange: document.getElementById("imageChanger"), //id of the image tag
imagePath: ["images/Ps_Logo.png", "images/Pencil.png"],
indexPos: 0,
ChangeImage: () => {
setInterval(() => {
indexObj.imageChange.src = indexObj.imagePath[indexObj.indexPos];
indexObj.imageChange.classList.add("imageToChange"); // imageToChange is the name of the css class where the animation is written on.
indexObj.indexPos++;
if (indexObj.indexPos === 2) {
indexObj.indexPos = 0;
}
}, 3000)
}
}
indexObj.ChangeImage();
Here is my css code. The class and animation keyframe:
.imageToChange {
height: 55px;
width: 70x;
border-radius: 20%;
animation-name: animateImage;
animation-duration: .5s;
animation-fill-mode: forwards;
}
#keyframes animateImage {
0% {
margin-top: 2px;
opacity: 0;
}
50% {
margin-top: 7;
}
100% {
opacity: 1;
margin-top: 9px;
}
}
The animation only runs the first time you add the .imageToChange class (and it does work with your code).
You need to either remove the class after the animation or switch to a different class each time you iterate an image.
Have you tried adding and removing (toggling on and off) on your animateImage class? Consider adding the animation class and then toggling it after the animation is completed.
You could use the addClass("imageToChange") and removeClass("imageToChange") jQuery methods: https://api.jquery.com/addClass/
Or using Vanilla JS toggle a class: https://www.w3schools.com/howto/howto_js_toggle_class.asp
Just be sure to retrigger the event the desired number of times.

How to set animation state to finish

I've created a slider animation as demonstrated below:
#mixin progress {
#-webkit-keyframes interval {
from {
width: 0;
}
to {
width: 100%;
}
}
animation: var(--duration) linear 0s interval;
animation-play-state: var(--playState);
}
.slider-item {
#include progress;
}
When a click event fires my task is to make the current slider animation be completed.
I have tried to select the target element for example:
this.$refs[`slider-item-${id}`]
Nevertheless, the animation property is still empty, is there something that i'm missing here? or is there a better alternative for that? (i have tried the API https://developer.mozilla.org/en-US/docs/Web/API/Element/animate without success)
Try to replace
animation: var(--duration) linear 0s interval;
with
animation: var(--duration) linear 10ms forwards;
to see the animation end as the last state remaining on your page.

How to remove a div with fade out effect in JavaScript?

I want to remove a div element on click event but i want to remove it with a fade out effect. I have got some JQuery solution but i need pure JavaScript or css solution.
document.querySelector('.list').addEventListener("click", function(e){
if (e.target.localName === "span") {
var removeTarget = e.target.parentNode.parentNode;
removeTarget.parentNode.removeChild(removeTarget);
};
});
This code is removing the div element with no effect. How can i add a fade out effect?
I've made this function a while ago for a personal project:
function removeFadeOut( el, speed ) {
var seconds = speed/1000;
el.style.transition = "opacity "+seconds+"s ease";
el.style.opacity = 0;
setTimeout(function() {
el.parentNode.removeChild(el);
}, speed);
}
removeFadeOut(document.getElementById('test'), 2000);
There are two ways you can achieve this: CSS3 animation or jQuery animation.
CSS3 Animation
In your CSS document, add:
.list {
opacity: 1;
-webkit-transition: opacity 1000ms linear;
transition: opacity 1000ms linear;
}
This will make any change of opacity to your item fade by 1000ms.
Change line 4 of your JavaScript to:
removeTarget.style.opacity = '0';
setTimeout(() => removeTarget.remove(), 1000);
This will make your item change opacity to 0, thus making the transition from step 1 have an effect. Then it will remove the item with your code after 1000ms.
Note: Make sure the time of the CSS3 transition and the setTimeout are the same.
jQuery Animation
Get jQuery
Go to the jQuery Website and download it, or
Add ` in your HTML document before any jQuery code.
Change line 4 of your Javascript to:
removeTarget.fadeOut(1000)
This will Fade Out your item by 1000ms, you can change this time to whatever you want.
In 2020 you can forgo use of use setTimeout for the animationend event, removing the need to maintain the duration in two places:
.fade-out {
animation: fade 2s;
-webkit-animation: fade 2s;
-moz-animation: fade 2s;
}
/* Animate opacity */
#keyframes fade {
from { opacity: 1 }
to { opacity: 0 }
}
#-moz-keyframes fade {
from { opacity: 1 }
to { opacity: 0 }
}
#-webkit-keyframes fade {
from { opacity: 1 }
to { opacity: 0 }
}
const elementToFade = document.getElementById('my-element');
elementToFade.onanimationend = (e) => {
if (e.target.classList.contains('fade-out')) {
elementToFade.parentNode.removeChild(elementToFade);
}
};
// To fade away:
elementToFade.classList.add('fade-out');
It's a good question, but to animate some element in html, this element has to exist while it is animating. So, you have some ways to do this, a good way is hide this element with CSS and after the animation you remove this element. While you hiding you can animate, you can see this example:
<style>
.hide{
opacity: 0;
}
.fade-out {
transition:1s linear all;
}
</style>
<span class="list fade-out">
This is a List, click me to hide
</span>
<script>
document.querySelector('.list').addEventListener("click", function(e) {
if (e.target.localName === "span") {
//Add CSS hide and animate with fade out
var currentCSS = this.className;
this.className = currentCSS + ' hide';
var removeTarget = e.target.parentNode.parentNode;
setTimeout(function(){
removeTarget.parentNode.removeChild(removeTarget);
},1000);
};
});
</script>
Add the following CSS class to the element using elem.className="my-animation"; on click:
.my-animation {
animation: fade 3s steps(90) forwards;
-webkit-animation: fade 3s steps(90) forwards;
-moz-animation: fade 3s steps(90) forwards;
}
#keyframes fade {
from {
opacity: 1;
}
to {
opacity: 0.0;
}
}
You may control the speed of the animation by modifying the steps(number) as well.
Just goto jQuery source code, take out the fade code which is in pure javascript, and use it, no need to reinvent the wheel,
or a hint is reduce the height of div to 0 slowly using setTimeInterval()
or a css solution would be to use transform and transition properties

How to pause a css animation, and then continue running from the pause point?

I'm playing a CSS animation with infinite iterations, until some point I pausing it from java script (using technique from here).
At later time I resume the animation. The problem is that the animation is restarting from the beginning point, and not from the last point before the pause.
Does there is a way to continue the animation from the pause point, without jumping to the start?
Edit: Between the pause and resume I also change the animation duration, see the demo.
You should see some 'jumping'. Need explanation about this strange behavior.
http://jsfiddle.net/zhang6464/MSqMQ/
Just switch animation-play-state css property to be paused, according to the article you supplied(http://css-tricks.com/restart-css-animation/
I've just started to dig into JS myself, so there are surely better ways to do this, but how about something like this - Demo (Unprefixed version).
CSS
#box {
position: relative;
top: 20px;
left: 20px;
width: 100px;
height: 100px;
background: #393939;
animation: move 2s linear infinite;
animation-play-state: running;
}
#keyframes move {
100% {
transform: rotate(360deg);
}
}
JS:
(function () {
var box = document.getElementById('box');
box.onclick = function () {
if (box.style.animationPlayState === "paused") {
box.style.animationPlayState = "running";
} else {
box.style.animationPlayState = "paused";
}
};
})();
Based on if the animation is running or paused I change the animation-play-state onclick.
EDIT: Added the css code.

Categories