Javascript animation fires intermittently - javascript

I have a Math game with a function to calculate the correct answer. If user answer correctly I want to show an animated images. I was able to achieve this but the animation it self work basically one time yes and one time not.
Do I miss something?
function checkAnswer() {
// Checks the answer against the first element in
// the returned calculateCorrectAnswer array
let userAnswer = parseInt(document.getElementById('answer-box').value);
let calculatedAnswer = calculateCorrectAnswer();
let isCorrect = userAnswer === calculatedAnswer[0];
if(isCorrect) {
incrementScore();
moveRight();
} else {
alert(`Awwww .... you answered ${userAnswer}. the correct answer was ${calculatedAnswer[0]} 😟`);
incrementWrongAnswer();
}
runGame(calculatedAnswer[1]);
}
function moveRight() {
let theImg = document.getElementById('myImg');
let msg = document.getElementById('message');
theImg.classList.toggle('fade-in');
msg.classList.toggle('fade-in');
}
// My CSS
#myImg.fade-in {
animation-name: fadeIn;
animation-duration: 2s;
}
#keyframes fadeIn {
0% {opacity: 0;}
100% {opacity: 1;}
}enter code here

In your case I'd use transition, instead of animation
The code would look like that:
#myImg {
opacity: 0;
transition: opacity 2s linear;
}
#myImg.fade-in {
opacity: 1;
}

find the solution, basically just removing the class and add again :)
function moveRight() {
let theImg = document.getElementById('myImg');
let msg = document.getElementById('message');
theImg.classList.remove('fade-in');
void theImg.offsetWidth;
theImg.classList.toggle('fade-in');
msg.classList.remove('fade-in');
void msg.offsetWidth;
msg.classList.toggle('fade-in');
}

Related

JavaScript help in animation

"I want disable fade-in and fade-out animation after one time its apply on whole web page"
I need a pure JavaScript code which disable fade-in and fade-out animation after it apply one time
.fade {
/* transition: opacity 0.9s ease-in;*/
opacity: 0;
}
.fade.visible {
transition: opacity 1s ease-in;
opacity: 1;
}
window.addEventListener('scroll', fade);
function fade()
{
let animation=document.querySelectorAll('.fade');
for (let i=0; i<animation.length; i++)
{
let windowheight=window.innerHeight;
let top=animation[i].getBoundingClientRect().top;
if (top < windowheight)
{
animation[i].classList.add('visible');
}
else
{
animation[i].classList.remove('visible');
}
}
}
Use a count variable. When the function that involves the fade-in and fade-out is triggered, add to the count variable. After it is increased, make it so these changes do not occur any more.
let count = 0;
count++;
If you want to have more code in the answer, post some more from your specific example.
This creates a count variable. If you want the animation to occur exactly once, then this should work as the count is increased by one after the animation occurs, making sure it will not happen again.
let count = 0;
window.addEventListener('scroll', fade);
function fade()
{
if (count < 1)
{
let animation=document.querySelectorAll('.fade');
for (let i=0; i<animation.length; i++)
{
let windowheight=window.innerHeight;
let top=animation[i].getBoundingClientRect().top;
if (top < windowheight)
{
animation[i].classList.add('visible');
}
else
{
animation[i].classList.remove('visible');
}
}
}
else
{
return;
}
count++;
}

How would I apply a fade out animation to each of the icons in my menu within a for loop

im currently working on an animation where there's a delay between each of the icons when fading out. The fade out animation works fine, but only on the first icon and im unsure on why this is. Could some one maybe point out the mistake im making?
Javascript code:
function closeHorizontalWindow()
{
const delay = 150;
const reasons = ['btnReady', 'btnNotReady', 'btnBreak', 'btnEmail', 'btnLunch',
'btnComfortBreak', 'btnMeeting', 'btnChat']
for (let i = 0; i < reasons.length; i++) {
document.getElementById(reasons[i]).style.animation = `reasonsfadeout 0.45s ease-out
forwards ${delay}ms`
delay+=150
}
CSS code:
#keyframes reasonsfadeout
{
from{opacity: 1; }
to {opacity: 0; }
}
}
Thankyou
You can use an interval to iterate instead of a regular for-loop.
function closeHorizontalWindow()
{
const delay = 150;
const reasons = ['btnReady', 'btnNotReady', 'btnBreak', 'btnEmail', 'btnLunch',
'btnComfortBreak', 'btnMeeting', 'btnChat']
let i = 0;
const interval = setInterval(function(){
document.getElementById(reasons[i]).style.animation = `reasonsfadeout 0.45s ease-out forwards ${delay}ms`;
i++;
if(i>=reasons.length){
clearInterval(interval);
}
}, delay);
}

javascript onclick css fade in each time, not just 1st time

How can I have text fade in on each click and not just the first time using css transition and JavaScript?
Here is what I have so far
<style>
#data {
transition: .7s;
}
</style>
<h1 id="data"></h1>
click 1
document.getElementById('data').style.opacity = 0;
function go(event){
event.preventDefault();
document.getElementById('data').style.opacity = 1;
document.getElementById('data').innerHTML = 'test';
}
document.getElementById('clicker').addEventListener('click', go);
It can also be done using Element.animate():
const dataElement = document.getElementById('data')
dataElement.style.opacity = 0
function go(event) {
event.preventDefault()
dataElement.animate({
opacity: [0, 1]
}, 700).onfinish = () => dataElement.style.opacity = 1
}
document.getElementById('clicker').addEventListener('click', go)
<h1 class="fade-in" id="data">test</h1>
click 1
EDIT:
In the above snippet onfinish event handler was used to maintain the final opacity value since it was being set back to 0 after the animation ends. But I found that this can also be achieved by setting fill: 'forwards' in the keyframe options:
const dataElement = document.getElementById('data')
dataElement.style.opacity = 0
function go(event) {
event.preventDefault()
dataElement.animate({
opacity: [0, 1]
}, {
duration: 700,
fill: 'forwards'
})
}
document.getElementById('clicker').addEventListener('click', go)
<h1 class="fade-in" id="data">test</h1>
click 1
Also you might want to check browser compatibility before implementing those approaches
And if you want a safer approach you may use css animations:
const data = document.getElementById('data')
data.style.opacity = 0
const clicker = document.getElementById('clicker')
clicker.addEventListener('click', () => {
data.classList.remove('fade-in')
data.offsetWidth // required to trigger a reflow and restart the animation
data.classList.add('fade-in')
})
.fade-in {
animation-name: fadein-animation;
animation-duration: 700ms;
animation-fill-mode: forwards;
}
#keyframes fadein-animation {
0% {
opacity: 0;
}
100% {
opacity: 1;
}
}
<h1 id="data">test</h1>
click 1
setTimeout might work for you. On click set it invisible immediately and use setTimeout to have a delay then show it again.
document.getElementById('data').style.opacity = 0;
document.getElementById('data').innerHTML = 'test';
function go(event){
event.preventDefault();
document.getElementById('data').style.opacity = 0;
setTimeout(() => {
document.getElementById('data').style.opacity = 1;
}, 1000);
}
document.getElementById('clicker').addEventListener('click', go);
#data {
transition: .7s;
}
<h1 id="data"></h1>
click 1
<h1 id="data" style="opacity:0"> </h1>
<button type="button" id="clicker">Fade In</button>
<script>
var data = document.getElementById('data');
function fadeIn(){
data.innerHTML = 'Data entered successfully.';
data.animate({opacity:[0,1]},{duration:400,fill:'forwards'});
}
document.getElementById('clicker').addEventListener('click',fadeIn);
</script>

How to play one css anmation before chaging innerHTML and another one after it?

What I need is this: when I click the button I want the old text to slowly disappear, then I want the new one to slowly appear.
But the disappear animation never gets played. Here's my code:
css
.quote-container {
opacity: 0;
}
.appear {
opacity: 0;
animation: fadeIn 1200ms ease-in forwards;
}
.disappear {
opacity: 1;
animation: fadeOut 1200ms ease-in;
}
#keyframes fadeIn {
from {
opacity: 0;
}
to {
opacity: 1;
}
}
#keyframes fadeOut {
from {
opacity: 1;
}
to {
opacity: 0;
}
}
javascript
let pickARandomQuote = () => {
index = Math.floor(Math.random() * quotes.length);
currentQuote = quotes[index].quote;
currentAuthor = quotes[index].author;
console.log(currentQuote + " \n" + currentAuthor);
let quoteContainer = document.getElementById("quote-container");
quoteContainer.classList.add("disappear");
void quoteContainer.offsetWidth;
quoteContainer.classList.remove("disappear");
void quoteContainer.offsetWidth;
quoteContainer.classList.remove("appear");
document.getElementById("text").innerHTML = currentQuote;
document.getElementById("author").innerHTML = "- " + currentAuthor;
void quoteContainer.offsetWidth;
quoteContainer.classList.add("appear");
return {
quote: currentQuote,
author: currentAuthor
};
};
document.addEventListener("DOMContentLoaded", pickARandomQuote);
let button = document.getElementById("new-quote");
if (button) {
button.addEventListener("click", pickARandomQuote);
}
It seems like the animation on the screen happens independently from the code, so "disappear" animation doesn't have enough time to get played. I tried "setTimeout", but it didn't help though.
You need to wait till disappear animation ends before executing appear.
One of the approaches is setTimeout function.
Example:
let pickARandomQuote = function() {
index = Math.floor(Math.random() * quotes.length);
currentQuote = quotes[index].quote;
currentAuthor = quotes[index].author;
let quoteContainer = document.getElementById("quote-container");
quoteContainer.classList.remove("appear");
quoteContainer.classList.add("disappear");
setTimeout(function () {
document.getElementById("text").innerHTML = currentQuote;
document.getElementById("author").innerHTML = "- " + currentAuthor;
quoteContainer.classList.remove("disappear");
quoteContainer.classList.add("appear");
}, this.duration)
};
document.addEventListener("DOMContentLoaded", { handleEvent: pickARandomQuote, duration: 0 });
let button = document.getElementById("new-quote");
if (button) {
button.addEventListener("click", { handleEvent: pickARandomQuote, duration: 1200 });
}
However, if you can use jQuery, the following Q&A may work for you.
Jquery replacewith fade/animate

Javascript function to FadeIn and FadeOut html item - working solution

HTML
<div id="notifyProductName">
Angualar JS
<a href="" ng-click="cart.addItem(product.name,product.price, 1);cart.ShowItem(product.name)">
JavaScript
cart.prototype.ShowItem = function (productName)
{
document.getElementById("notifyProductName").innerHTML = productName";
document.getElementById("notifyProductName").fadeOut(400);
}
I want to display the productName in a html message box and then fade the message box out after a few seconds.
Set a 3 second setTimeout() function and use a CSS class with transition on opacity for the fade.
cart.prototype.ShowItem = function (productName)
{
var el = document.getElementById("notifyProductName");
el.innerHTML = productName;
el.classList.remove('fade');
el.classList.add('show');
var timeout = setTimeout(function() {
el.classList.add('fade');
}, 3000);
}
.notifyProductName {
opacity: 0;
}
.show {
opacity: 1;
}
.fade {
opacity: 0;
transition: opacity .5s;
}
<div id="notifyProductName" class="notifyProductName"></div>

Categories