I'm a bit confused about how to trigger multiple animations for an element using javascript.
I'm trying to get an element (.hud) to fade-in and also bounce when clicked. Currently it will only do one or the other. The second animation class is being added to the element in a on click event. The class gets added but the animation does not play. How would I construct my code for the animation to fade-in and also bounce on click?
<!DOCTYPE html>
<html>
<head>
<style>
.anim {
animation-name: bounceIn_1;
animation-duration: .5s;
}
.hud {
width: 100px;
height: 100px;
background-color: red;
animation-name: fade-in;
animation-duration: .5s;
}
#-webkit-keyframes fade-in {
0% {
opacity: 0; }
100% {
opacity: 1; } }
#-webkit-keyframes bounceIn_1{0%,20%,40%,60%,80%,to{-webkit-animation-timing-function:cubic-bezier(.215,.61,.355,1);animation-timing-function:cubic-bezier(.215,.61,.355,1)}0%{opacity:0;-webkit-transform:scale3d(.3,.3,.3);transform:scale3d(.3,.3,.3)}20%{-webkit-transform:scale3d(1.1,1.1,1.1);transform:scale3d(1.1,1.1,1.1)}40%{-webkit-transform:scale3d(.9,.9,.9);transform:scale3d(.9,.9,.9)}60%{opacity:1;-webkit-transform:scale3d(1.03,1.03,1.03);transform:scale3d(1.03,1.03,1.03)}80%{-webkit-transform:scale3d(.97,.97,.97);transform:scale3d(.97,.97,.97)}to{opacity:1;-webkit-transform:scaleX(1);transform:scaleX(1)}}
</style>
</head>
<body>
<p>This box should fade in and bounce on click</p>
<div class="hud"></div>
<script>
element = document.querySelector('.hud');
console.log(element);
// reset the transition by...
element.addEventListener("click", function(e) {
console.log("clicked");
e.preventDefault;
element.classList.remove("anim");
void element.offsetWidth;
element.classList.add("anim");
}, false);
</script>
</body>
</html>
Was it so necessary for you? In order for the animation in your example to work constantly, a reset function is needed.
element = document.querySelector('#red_box');
console.log(element);
element.addEventListener("click", function(e) {
e.preventDefault;
console.log("clicked");
element.classList.remove("hud");
element.classList.remove("anim");
void element.offsetWidth;
element.classList.add("anim");
}, false);
/*$(".hud").click(function () {
var $this = $(this);
$this = reset($this);
$this.addClass("anim bounceIn_1");
console.log("clicked");
});*/
.anim {
width: 100px;
height: 100px;
background-color: red;
animation-name: bounceIn_1;
animation-duration: .5s;
}
.hud {
width: 100px;
height: 100px;
background-color: red;
animation-name: fade-in;
animation-duration: .5s;
}
#-webkit-keyframes fade-in {
0% {
opacity: 0; }
100% {
opacity: 1; } }
#-webkit-keyframes bounceIn_1 {0%,20%,40%,60%,80%,to{-webkit-animation-timing-function:cubic-bezier(.215,.61,.355,1);animation-timing-function:cubic-bezier(.215,.61,.355,1)}0%{opacity:0;-webkit-transform:scale3d(.3,.3,.3);transform:scale3d(.3,.3,.3)}20%{-webkit-transform:scale3d(1.1,1.1,1.1);transform:scale3d(1.1,1.1,1.1)}40%{-webkit-transform:scale3d(.9,.9,.9);transform:scale3d(.9,.9,.9)}60%{opacity:1;-webkit-transform:scale3d(1.03,1.03,1.03);transform:scale3d(1.03,1.03,1.03)}80%{-webkit-transform:scale3d(.97,.97,.97);transform:scale3d(.97,.97,.97)}to{opacity:1;-webkit-transform:scaleX(1);transform:scaleX(1)}}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<body>
<p>This box should fade in and bounce on click</p>
<div id="red_box" class="hud"></div>
</body>
Have you tried to put a comma in your .anim class?
animation: bounceIn_1 .5s, fade-in .5s
You need to put the 2 animation in the same css class and make sure that the removing and the adding of that class are done in 2 separate frames.
The first issue can be easily solved by putting a comma between the 2 animations which are now in the class .anim.
The second issue is a little bit tricky but the window.requestAnimationFrame() function will solve it !
Here you have the modified code so that you can better understand:
element = document.querySelector('.hud');
console.log(element);
// reset the transition by...
element.addEventListener("click", function(e) {
console.log("clicked");
e.preventDefault;
element.classList.remove("anim");
void element.offsetWidth;
window.requestAnimationFrame(() => element.classList.add("anim")); /* The add() will be done before the next repaint so that we can see the change */
}, false);
.anim {
animation-name: fade-in, bounceIn_1;
animation-duration: .5s;
}
.hud {
width: 100px;
height: 100px;
background-color: red;
//animation-name: fade-in; /* Remove this */
//animation-duration: .5s; /* Remove this */
}
#-webkit-keyframes fade-in {
0% {
opacity: 0; }
100% {
opacity: 1; } }
#-webkit-keyframes bounceIn_1{0%,20%,40%,60%,80%,to{-webkit-animation-timing-function:cubic-bezier(.215,.61,.355,1);animation-timing-function:cubic-bezier(.215,.61,.355,1)}0%{opacity:0;-webkit-transform:scale3d(.3,.3,.3);transform:scale3d(.3,.3,.3)}20%{-webkit-transform:scale3d(1.1,1.1,1.1);transform:scale3d(1.1,1.1,1.1)}40%{-webkit-transform:scale3d(.9,.9,.9);transform:scale3d(.9,.9,.9)}60%{opacity:1;-webkit-transform:scale3d(1.03,1.03,1.03);transform:scale3d(1.03,1.03,1.03)}80%{-webkit-transform:scale3d(.97,.97,.97);transform:scale3d(.97,.97,.97)}to{opacity:1;-webkit-transform:scaleX(1);transform:scaleX(1)}}
<body>
<p>This box should fade in and bounce on click</p>
<div class="hud"></div>
</body>
Quick tip: with this method you can play as many animation as you want on the same element, just add its name to the .anim animations list and you're done!
I am trying to use animate to make images transition from zero opacity to full opacity. The keyframes animation code i have used works but i want to delay the start until the image is in view.
I have tried several JS codes which have not worked.
HTML
<div class="item2">
<img src="images/winston-chen-qg8TGmBNdeY-unsplash.jpg" width="950" height="700" alt="wintson cheng unsplash" class="img">
</div>
CSS
#keyframes animate {
from {opacity: 0;}
to {opacity: 1;}
}
.img {
width: 100vw;
height: auto;
animation-name: animate;
animation-duration: 10s;
animation-timing-function: ease-in;
}
You could do it easily with jQuery.
CSS:
img { opacity: 0; } /* this sets the opacity before it comes in so there isn't a jump */
.img {
width: 100vw;
height: auto;
}
.fadein {
animation: animate 10s forwards;
}
jQuery:
https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js
Then in scripts file:
$(function() {
$(window).scroll(function() {
var $img = $(".img");
$img.each(function() {
var $y = $(document).scrollTop(),
$wh = $(window).height(),
$t = $(this).offset().top - $wh;
if ($y > $t) {
$(this).addClass("fadein");
}
});
});
});
Every time the .img tag comes into view it adds the fadein class and fades in.
Long story short, why doesn't this work? It seems to be running the setTimeout line once, but it won't repeat. It's supposed to decrease the alpha of the target element's background color by 0.1 every 500ms until it reaches zero, but by my reckoning it only makes it to 0.9 before the function stops... It's insanely simple but I can't find any info here or elsewhere which addresses something like this.
EDIT: Thanks for the answers, got it working with setInterval. CSS definitely provides a more elegant solution, but I should have mentioned that this is for an assignment in which we're supposed to use javascript instead.
function highlight(which){
var target=document.getElementById(which);
var a_value=1.0;
if(a_value<0){
return;
}
target.style.backgroundColor="rgba(255,255,0,"+a_value+")";
setTimeout(function(){target.style.backgroundColor="rgba(255,255,0,"+(a_value -= 0.1)+")";}, 500);
}
setTimeout only fires once. If you want something to keep repeating at an interval, then you should call setInterval instead. However, you should remember to cancel this repeating timer when your animation has finished.
When you call setInterval it returns a number that is essentially a handle to your timer. You can then cancel the timer later by passing this number to clearInterval().
Here's a revised function:
function highlight(which)
{
var target = document.getElementById(which);
var a_value = 1.0;
target.style.backgroundColor = "rgba(255,255,0," + a_value + ")";
let handle = setInterval(function ()
{
if (a_value < 0)
{
clearInterval(handle);
return;
}
target.style.backgroundColor = "rgba(255,255,0," + (a_value -= 0.1) + ")";
}, 500);
}
However, the comments on this question are correct in pointing out that it doesn't really make sense to do this type of animation with JavaScript anymore. You should look into CSS transitions.
If You're asking about running same code periodically so - read about setInterval, clearInterval or make a method and call setTimeout inside of function again via passing period.
But if You're asking question about how to animate somethings, so - use css animations and don't "reinvent the wheel" (:
function fadeIn(which){
document.getElementById(which).classList.add("fadeIn");
}
fadeIn('fadeitin');
function fadeOut(which){
document.getElementById(which).classList.add("fadeOut");
}
fadeOut('fadeitout');
#fadeitin {
position: absolute;
left: 0; top: 0;
width: 200px;
height: 200px;
background: #f00;
opacity: 0;
}
#fadeitout {
position: absolute;
right: 0; top: 0;
width: 200px;
height: 200px;
background: #00f;
opacity: 1;
}
#-webkit-keyframes fadeIn {
0% {opacity: 0;}
100% {opacity: 1;}
}
#keyframes fadeIn {
0% {opacity: 0;}
100% {opacity: 1;}
}
.fadeIn {
-webkit-animation-name: fadeIn;
animation-name: fadeIn;
-webkit-animation-duration: 5s;
animation-duration: 5s;
-webkit-animation-fill-mode: both;
animation-fill-mode: both;
}
#-webkit-keyframes fadeOut {
0% {opacity: 1;}
100% {opacity: 0;}
}
#keyframes fadeOut {
0% {opacity: 1;}
100% {opacity: 0;}
}
.fadeOut {
-webkit-animation-name: fadeOut;
animation-name: fadeOut;
-webkit-animation-duration: 5s;
animation-duration: 5s;
-webkit-animation-fill-mode: both;
animation-fill-mode: both;
}
<div id="fadeitin"></div>
<div id="fadeitout"></div>
p.s. You can use jQuery and fadeIn, fadeOut methods.
As stated, setTimeout() only counts up to the time and fires the callback function once. But, you can make it run multiple times with a recursive function call. This is sometimes preferred over setInterval() because of the performance differences between the two.
var a_value = 1.0; // Needs to be outside of function to only be used once
function highlight(which){
if(a_value < 0){ return; }
// Instead of changing only the alpha of an RGB, just change the opacity
which.style.opacity = (a_value -= 0.1);
setTimeout(function(){
highlight(which); // recursive call
}, 500);
}
highlight(document.getElementById("test"));
#test {
height:100px;
background-color:yellow;
}
<div id="test"></div>
But really, this can all be done with a CSS animation and no JavaScript:
#test {
height:100px;
background-color:yellow;
animation-name: fade;
animation-duration: 3s;
animation-iteration-count: 1;
}
#keyframes fade {
from { opacity:1; }
to { opacity:0 }
}
<div id="test"></div>
I am creating a small game, where an element bounces from the top to the bottom of its parent element, and vice versa. Once the user clicks the element, the speed increases JSFiddle.
I am using the following CSS properties to set values (I have omitted the prefixes):
#ball {
animation-name: bounce;
animation-duration: 2s;
animation-direction: alternate;
animation-iteration-count: infinite;
}
#keyframes bounce {
0% {
width: 80px;
height: 80px;
margin-top: 0;
}
100% {
width: 80px;
height: 80px;
margin-top: 420px;
}
}
The JavaScript code I am using to change the duration of the animation:
var ball = document.getElementById('ball');
ball.onclick = function() {
ball.style.WebkitAnimationDuration = '100ms';
ball.style.MozAnimationDuration = '100ms';
ball.style.OAnimationDuration = '100ms';
ball.style.animationDuration = '100ms';
};
My question is as follows: Why does the animation-duration not change?
This is the problem:
ball.style.animationDuration = '100ms';
It should be like so:
ball.style.AnimationDuration = '100ms';
I'm working on a game and just found out about -webkit-animation-play-state CSS attribute. I want certain text to show itself as a short animation, then hide and show when called again (in javascript).
I figured out how to start animation when I want to in javascript, but after its finished, the text stays on the screen, which I don't want to.
HTML:
<p id="INFO">
TEST
</p>
CSS:
#-webkit-keyframes pulse {
from {
opacity: 0.0;
font-size: 100%;
}
to {
opacity: 1.0;
font-size: 400%;
}
}
#INFO {
position: absolute;
left: 400px;
top: 200px;
-webkit-animation-name: pulse;
-webkit-animation-duration: 1s;
-webkit-animation-iteration-count: 1;
-webkit-animation-timing-function: ease-in-out;
-webkit-animation-play-state:paused;
visibility: hidden;
}
JS:
var INFO = document.getElementById("INFO");
INFO.innerHTML = "WRONG";
INFO.style.color = "RED";
INFO.style.webkitAnimationPlayState = "running";
INFO.style.visibility = "visible";
I read some questions/answers about -webkit-animation-play-state on this site, but none regarding the issue I am having.
One thing I read about was that animation goes to its default values when its ended. But my default values say that animation is "hidden" ? source: how to stop my webkit frame animation?
If anyone can point me in the right direction I'd be grateful.
If I was not clear enough, ask for more info please.
Thank you
For what you are trying to do, you don't need to use -webkit-animation-play-state.
Instead, try starting the animation by applying a class with the animation properties set. Then use a JavaScript event listener to remove the class once the animation finishes.
You should also keep the element hidden with opacity instead of visibility:hidden since you are manipulating the opacity in the animation.
CSS:
#-webkit-keyframes pulse {
from {
opacity: 0.0;
font-size: 100%;
}
to {
opacity: 1.0;
font-size: 400%;
}
}
#INFO {
opacity:0;
position: absolute;
left: 400px;
top: 200px;
}
.pulse {
-webkit-animation-name: pulse;
-webkit-animation-duration: 1s;
-webkit-animation-iteration-count: 1;
-webkit-animation-timing-function: ease-in-out;
}
JS:
var INFO = document.getElementById("INFO");
INFO.innerHTML = "WRONG";
INFO.style.color = "RED";
INFO.addEventListener('webkitAnimationEnd', function (e) {
this.classList.remove('pulse');
});
DEMO >> CodePen