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.
Related
I have a spinning arrows image. On click, it refreshes a captcha. I have it defined in a short css, with a rotation function called on click.
These are the CSS, the HTML and the Javascript:
function rotatearrow() {
arrowreload.style.webkitTransform = 'rotate(360deg)';
arrowreload.style.MozTransform = 'rotate(360deg)';
arrowreload.style.msTransform = 'rotate(360deg)';
}
function reloadcaptcha() {
//does what's needed and plays perfectly
}
.reload {
max-width: 32px;
height: auto;
transform: rotate(0);
transition: all 0.8s;
}
<img id="arrowreload" class="reload" src="../images/reload.png" onclick="rotatearrow(); reloadcaptcha();">
Now the point is: rotatearrow plays at the first click and rotate the arrows, but it never plays after the first time. What am I doing wrong? What changes I have to do to the code?
Every time you click you need to increment the degree:
let degree = 0;
function rotatearrow() {
degree += 360;
arrowreload.style.webkitTransform = `rotate(${degree}deg)`;
}
.reload {
max-width: 32px;
height: auto;
transform: rotate(0);
transition: all 0.8s;
}
<img id="arrowreload" class="reload" src="http://pluspng.com/img-png/triangle-png-triangle-png-clipart-2400.png" onclick="rotatearrow();">
This will work, we just need to keep incrementing the rotation value in multiples i.e -- 360,720,1080.....
function rotatearrow() {
var transformValue = document.getElementById('arrowreload').style.webkitTransform;
var transformInteger = transformValue ? ((transformValue.match(/\d+/g).map(Number)[0]/360)+1) : 1;
document.getElementById('arrowreload').style.webkitTransform = 'rotate('+(360*transformInteger)+'deg)';
}
Hope this is helpful, also this doesn't require external variable declaration...
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
I want my custom element to move to the right for 200px when clicking a button. So the element starts moving on click. When in the animation I want to be able to click the button again to stop and let the element have an animated return to initial state (reverse animation from the current state).
I accomplished this with css transitions:
var state = false;
var button = document.getElementById("but");
button.onclick = clickA;
function clickA(){
state = !state;
var el = document.getElementById("el");
if (state) el.setAttribute("class", "animatedElement open");
else el.setAttribute("class", "animatedElement");
}
.animatedElement {
padding-left: 0px;
transition: padding-left 5s;
}
.open {
padding-left: 200px;
}
<button id="but">Click</button>
<div id="el">element</div>
So on click I just toggle the .open class on the component.
I want to know if this is possible to do with css animations? I tried this:
var state = false;
var button = document.getElementById("but");
button.onclick = clickA;
function clickA(){
state = !state;
var el = document.getElementById("el");
if (state) el.setAttribute("class", "animatedComponent-open");
else el.setAttribute("class", "animatedComponent-close");
}
#keyframes animationOpen {
0% {padding-left: 0px;}
100% {padding-left: 200px;}
}
.animatedComponent-open {
animation: animationOpen 3s normal forwards;
}
#keyframes animationClose {
0% {padding-left: 0px;}
100% {padding-left: 200px;}
}
.animatedComponent-close {
animation: animationClose 3s reverse forwards;
}
<button id="but">Click</button>
<div id="el">element</div>
But this doesn't revert open animation when clicked in the middle of animation, but jumps to the final state and then plays close animation from beginning.
As the keyframes have a starting point and and ending point, so they will start from those positions no matter where where the current position of the element is. Since you are using js to toggle, transitions are the way to go. Animations are just complicating it more without any benefits.
Visit https://css-tricks.com/controlling-css-animations-transitions-javascript/
I am sure this article will have the exact answer for you. There are many work arounds to get the current keyframe values at an animation playstate of pause.
Then with these values you can use the animate api to build a reverse animation.
If you can pass the reverse animation the pause keyframe values as starting-position values. Then you can set your animation end keyframes to paddingLeft:0px - just how it started.
This will solve the unwanted jumping to the end of the animation.
I'm making a website which will let you update an SQL table, and I want to add some sort of feedback when a button is clicked. I have made an invisible button (opacity=0) which lies to the right of each row as a status. I made this JS fade() function to set the opacity to 1, then slowly bring it back to 0, so a message pops up then fades away.
function fade () {
var invis = document.getElementById("invis".concat(num.toString()));
if(invis.style.opacity > .990) {
invis.style.opacity = (invis.style.opacity) - .001;
setTimeout(fade, 50);
} else if(invis.style.opacity > 0) {
invis.style.opacity = (invis.style.opacity) - .05;
setTimeout(fade, 50);
}
}
The trouble is, since webpages are single-threaded, any other action will interrupt the animation and leave behind a half-faded status. So that's no good. So now I am trying to set up the invisible buttons to change class when a new row is updated. The new class looks like this:
.invisible_anim {
...
opacity: 0;
animation:trans 3000ms;
}
#keyframes trans {
0% {
opacity: 1;
}
50% {
opacity: 1;
}
This works fine, except it only works once. From here I cannot get the animation to play a second time. I have tried changing the class back to "invisible" then "invisible_anim" with no luck. I also can't use JQuery or Webkit. I'm wondering if there's some flag you can set for a button without actually clicking on it so I can reset the class when I need to? Or even some way to thread my JS function so I can stick with that.
If you would like to play the animation multiple times (see docs here: https://developer.mozilla.org/en-US/docs/Web/CSS/animation), if you would like to play it twice only.
so this:
.invisible_anim {
...
opacity: 0;
animation:trans 3000ms;
}
#keyframes trans {
0% {
opacity: 1;
}
50% {
opacity: 1;
}
would turn to
.invisible_anim {
...
opacity: 0;
animation:trans 3s 2 ;
}
#keyframes trans {
0% {
opacity: 1;
}
50% {
opacity: 1;
}
EDIT:
Apparently the requirements are different than what I thought. Instead the solution seems to be to key off the animation event located at https://developer.mozilla.org/en-US/docs/Web/Guide/CSS/Using_CSS_animations and then when that animation done do what you need to do: so in JS-only
var e = document.getElementById("watchme");
e.addEventListener("animationend", listener, false);
function listener(){
//do what you need to do here
}
Just be careful, the reason for this is that most browsers have different "animationend" events that fire at different times. So definitely will need to be tested in different browsers to make sure that the animation event is firing at the right time. There's a post at (https://css-tricks.com/controlling-css-animations-transitions-javascript/) that details some of the issues you might encounter.
Have you considered using the CSS property "transition"? JavaScript has an event listener called "transitionend" that can trigger when your transition has ended, which you can use to reset the button.
First set the area for your alert button with the id invis.
CSS:
#invis {
opacity: 1;
transition: opacity 3s;
}
Then in JavaScript, generate your button and its content, which will appear at opacity 1, then transition to opacity 0. Your addEventListener will trigger when the animation is done, remove the button and reset the opacity for the next trigger.
JavaScript:
var invis = getElementByID("invis");
function fade() {
var button = document.createElement("button");
invis.appendChild(button);
invis.style.opacity = ("0");
invis.addEventListener("transitionend", function(){
invis.removeChild(button);
invis.style.opacity = ("1");
});
}
You can add the fade() function to your EventListener for the user "click."
This is my first time answering on StackOverflow, I hope this helps!
You need to start transparent then show then hide:
#keyframes trans {
0% {
opacity: 0;
}
50% {
opacity: 1;
}
100% {
opacity: 0;
}
}
Then simply add your class (remove after the 3000ms time period)
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.