After pressing button the animation does not repeat - javascript

What am I doing wrong, that after pressing the button the animation does not repeat? Thanks for help.
var abox = document.getElementsByClassName("box")[0];
function allmove(){
abox.classList.toggle("move");
}
.vector img {
width: 20%;
height: 20%;
position: relative;
animation-name: example;
animation-duration: 4s;
animation-iteration-count: 1;
}
#-webkit-keyframes example{
0%{left:0px; top:0px;}
25%{left:200px; top:0px;}
100%{left:0px; top:0px;}
}
<div class="box"></div>
<div class="vector">
<img src="https://encrypted-tbn0.gstatic.com/images?q=tbn%3AANd9GcSqYooppFTzO8AydhbeZtjnrWpeZS5b7Gbi9EnwEPuuPW_t6ycn" />
</div>
<button class="button" onclick="allmove()">Click Me</button>

You can use something like this to refresh animation on click.
I added .animation class to separate it from vector class.This way you can easly toggle it.
the setTimeout is to wait a moment before adding the class after removing it.
var abox = document.getElementsByClassName("animation")[0];
function allmove(){
abox.classList.remove("animation");
setTimeout(function(){ abox.classList.add('animation') }, 100);
}
.vector img {
width: 20%;
height: 20%;
position: relative;
}
.animation img {
animation-name: example;
animation-duration: 4s;
animation-iteration-count: 1;
}
#-webkit-keyframes example{
0%{left:0px; top:0px;}
25%{left:200px; top:0px;}
100%{left:0px; top:0px;}
}
<div class="box"></div>
<div class="vector animation">
<img src="https://encrypted-tbn0.gstatic.com/images?q=tbn%3AANd9GcSqYooppFTzO8AydhbeZtjnrWpeZS5b7Gbi9EnwEPuuPW_t6ycn" />
</div>
<button class="button" onclick="allmove()">Click Me</button>

That's it, but I think addEventListener is better than onclick()
I modify a bit your code
You can find jsfiddle example Here
const bike = document.querySelector(".bike");
const button = document.querySelector(".button");
function allMove(){
bike.classList.toggle("move");
}
button.addEventListener('click', allMove);
.vector img {
width: 20%;
height: 20%;
position: relative;
}
.move{
animation-name: example;
animation-duration: 4s;
animation-iteration-count: 1;
}
#-webkit-keyframes example{
0%{left:0px; top:0px;}
25%{left:200px; top:0px;}
100%{left:0px; top:0px;}
}
<div class="box"></div>
<div class="vector">
<img class="bike" src="https://encrypted-tbn0.gstatic.com/images?q=tbn%3AANd9GcSqYooppFTzO8AydhbeZtjnrWpeZS5b7Gbi9EnwEPuuPW_t6ycn" />
</div>
<button class="button">Click Me</button>

Inspired by Mehdi Ayari's answer, but I think using requestAnimationFrame is better than using a timeout.
var abox = document.querySelector(".animation");
function allmove() {
requestAnimationFrame(() => {
abox.classList.remove("animation");
requestAnimationFrame(() => abox.classList.add("animation"));
});
}
.vector img {
width: 20%;
height: 20%;
position: relative;
}
.animation img {
animation-name: example;
animation-duration: 4s;
animation-iteration-count: 1;
}
#-webkit-keyframes example{
0%{left:0px; top:0px;}
25%{left:200px; top:0px;}
100%{left:0px; top:0px;}
}
<div class="box"></div>
<div class="vector animation">
<img src="https://encrypted-tbn0.gstatic.com/images?q=tbn%3AANd9GcSqYooppFTzO8AydhbeZtjnrWpeZS5b7Gbi9EnwEPuuPW_t6ycn" />
</div>
<button class="button" onclick="allmove()">Click Me</button>

Related

How do I index unhidden element on top, instead of whatever is next in the DOM?

I am trying to code a card drawing emulation and I have run into a problem. After I've flipped a random card I cannot get that exact card to stay on top - instead whatever is furthest down in the DOM stays on top, and the other cards just falls below it.
I have tried with Z-index (which did nothing), and I believe this might be the answer, but I think I'm overseeing something. Also tried to hide the element with a timer, which still causes overlapping issues.
Anyone who could point me in the direction of how to make the pulled card stay on top regardless of it's placement within the DOM? I've even tried to give DOM element further up higher z-index which does nothing to the order. So I have a hard time finding the problem!
JSFiddle
Full code:
// Functions for displaying the random content when card is clicked
var backgroundImage = document.getElementById("bg");
function first_function(){
console.log("test1");
document.getElementById("a").classList.remove("hide");
document.getElementById("a2").classList.remove("hide");
document.getElementById("a").style.color = "white";
}
function second_function(){
console.log("test2");
document.getElementById("b").classList.remove("hide");
document.getElementById("b2").classList.remove("hide");
document.getElementById("b").style.color = "white";
}
function third_function(){
console.log("test3");
document.getElementById("c").classList.remove("hide");
document.getElementById("c2").classList.remove("hide");
document.getElementById("c").style.color = "white";
}
function last_card(){
console.log("last one");
document.getElementById("last").classList.remove("hide");
document.getElementById("last2").classList.remove("hide");
document.getElementById("last").style.color = "white";
}
// Splice array 1 item at a time
Array.prototype.randsplice = function () {
var randomnbr = Math.floor(Math.random() * this.length);
// Removed extra variable
return this.splice(randomnbr, 1);
};
// Use an eventlistener to wait for the DOM to load so that we can depend on DOM elements being available
window.addEventListener("load",function(){
// Setup the array we will use for this example
var my_array = [
first_function,
second_function,
third_function,
];
// Attach a click event handler to our button
backgroundImage.onclick = function(){
// Hide content after each click
var list = document.getElementsByClassName("hide-all");
for(var i=0;i<list.length;i++){
list[i].classList.add("hide");
}
// Modify my_array and display result
if(my_array.length > 0){
var new_numb = my_array.randsplice();
new_numb[0].apply(null);
// Animation making card unclickable until animation is complete
backgroundImage.classList.add("animstart");
backgroundImage.addEventListener( "animationend", function() {
backgroundImage.classList.remove("animstart");
} );
// Check if the array is empty and if so, perhaps display a message
}else{
last_card();
backgroundImage.classList.add("no-click");
}
}
});
body, html{
height: 100%;
margin: 0;
background-color: #333;
}
/* Background card */
.bgcard{
width:9.4vw;
display: inline-block;
position:absolute;
left:35.4%;
top:66.2%;
cursor: pointer;
}
/* Animation making card unclickable start */
.animstart{
animation-name: examples;
animation-duration: 1s;
}
#keyframes examples {
0% { pointer-events: none;}
100% { pointer-events: none;}
}
.cards{
z-index: 100;
transform: rotateY(180deg);
width: 14vw;
font-size: 1.2vw;
transition: 0.6s;
transform-style: preserve-3d;
position: relative;
animation-name: flip;
animation-duration: 0.6s;
animation-fill-mode: forwards;
animation-delay: 0s;
}
#keyframes flip {
from { transform: rotateY(180deg); left: -10vw; }
to { transform: rotateY(0deg); left: 0vw; }
}
#keyframes flips {
from { transform: rotateY(0deg); left: -10vw; }
to { transform: rotateY(180deg); left: 0vw; }
}
.frontcard {
width: 14vw;
z-index: 200;
transform: rotateY(0deg);
transition: 0.6s;
transform-style: preserve-3d;
position: relative;
animation-name: flips;
animation-duration: 0.6s;
animation-fill-mode: forwards;
animation-delay: 0s;
}
.frontcard, .back {
backface-visibility: hidden;
position: absolute;
}
.text-wrap{
padding-left: 200px;
width: 50vw;
position: absolute;
}
p{
top: 10%;
animation-name: hidden;
animation-duration: 0.6s;
}
h2{
top: 5%;
animation-name: hidden;
animation-duration: 0.6s;
}
.pulled-card-container{
position: absolute;
right: 24%;
top:66.2%;;
display: inline-block;
z-index: 100;
perspective: 1000;
}
.pulled-card-container-done{
position: absolute;
right: 24%;
top:66.2%;;
display: inline-block;
}
#keyframes example {
0% { left:-10vw;}
25% { left:0px;}
50% { left:0px;}
75% { left:0px;}
100% { left:0px;}
}
#keyframes hidden {
0% {opacity: 0;}
25% {opacity: 0;}
50% {opacity: 0;}
75% {opacity: 0;}
100% {opacity: 1;}
}
.no-click{
pointer-events: none;
cursor: none;
}
.hide{
display: none;
}
.hideanim{
opacity: 1;
-webkit-animation-delay: 1s;
-webkit-animation-name: fadein;
-webkit-animation-duration: 1s;
-webkit-animation-timing-function: linear;
animation-fill-mode: forwards;
animation-delay: 1s;
animation-name: fadein;
animation-duration: 1s;
animation-timing-function: linear;
}
#-webkit-keyframes fadein {
from {
opacity: 1;
}
to {
opacity: 0;
}
}
#keyframes fadein {
from {
opacity: 1;
}
to {
opacity: 0;
}
}
<div class="all-wrap">
<!-- Containers with information -->
<div id="a" class="aa hide ">
<div id="a2" class="text-wrap hide hide-all">
<h2>X of Cards</h2>
<p>First Displayed Text</p>
</div>
<div class="pulled-card-container">
<img class="cards lol1"src="https://cdn2.bigcommerce.com/n-d57o0b/1kujmu/products/297/images/924/2D__57497.1440113502.1280.1280.png?c=2" width="200px" height="300px">
<img src="https://st.depositphotos.com/1363007/1810/i/950/depositphotos_18105995-stock-photo-card-back.jpg" alt="" width="200px" height="300px" alt="" class="frontcard">
</div>
</div>
<div id="b" class="ab hide">
<div id="b2" class="text-wrap hide hide-all">
<h2>Y of Cards</h2>
<p>Second displayed text</p>
</div>
<div class="pulled-card-container">
<img class="cards lol2"src="https://cdn2.bigcommerce.com/n-d57o0b/1kujmu/products/297/images/928/6D__92916.1440113530.1280.1280.png?c=2" width="200px" height="300px">
<img src="https://st.depositphotos.com/1363007/1810/i/950/depositphotos_18105995-stock-photo-card-back.jpg" alt="" width="200px" height="300px" alt="" class="frontcard">
</div>
</div>
<div id="c" class="ac hide">
<div id="c2" class="text-wrap hide hide-all">
<h2>Z of Cards</h2>
<p>Third displayed text</p>
</div>
<div class="pulled-card-container">
<img class="cards lol3"src="https://cdn2.bigcommerce.com/n-d57o0b/1kujmu/products/297/images/932/10H__11470.1440113568.1280.1280.png?c=2" width="200px" height="300px">
<img src="https://st.depositphotos.com/1363007/1810/i/950/depositphotos_18105995-stock-photo-card-back.jpg" alt="" width="200px" height="300px" alt="" class="frontcard">
</div>
</div>
<div id="last" class="hide">
<div id="last2" class="text-wrap hide hide-all">
<h2>Last of Cards</h2>
<p>The last card in the deck</p>
</div>
<div class="pulled-card-container">
<img class="cards" src="https://cdn2.bigcommerce.com/n-d57o0b/1kujmu/products/297/images/932/10H__11470.1440113568.1280.1280.png?c=2" alt="" width="200px" height="300px">
<img src="https://st.depositphotos.com/1363007/1810/i/950/depositphotos_18105995-stock-photo-card-back.jpg" alt="" width="200px" height="300px" alt="" class="frontcard">
</div>
</div>
<!-- Background card -->
<div class="bgcard" id="bg">
<img src="https://st.depositphotos.com/1363007/1810/i/950/depositphotos_18105995-stock-photo-card-back.jpg" alt="" width="200px" height="300px">
</div>
</div>
Any help is greatly appreciated!
When using z-index, you will need to set the position to relative or absolute ... pretty sure, like 90% sure.
After fidgeting around some more I found my grave error. Here's the answer, in case anyone ever wonders:
I had z-index on pulled-card-container that conflicted. After removing that, and doing a
var zNumb = 300;
zNumb++;
document.getElementById("imgOne").style.zIndex = zNumb;
on each function it worked like a charm!

Is there a way to make a CSS animation run again on repeated clicks of a button without using timeout? [duplicate]

This question already has answers here:
Restart animation in CSS3: any better way than removing the element?
(14 answers)
Closed 1 year ago.
I am trying to get an animation to run whenever a button is clicked. Right now, it only runs if the page is refreshed and does not run again on repeated clicks of the button.
function myPlayFunction(el){ document.getElementById("myTest").style.animationPlayState = "running";
}
#myTest {
width: 100px;
height: 100px;
background: red;
position: relative;
animation-name: example;
animation-duration: 3s;
animation-delay: 1s;
animation-play-state: paused;
}
#keyframes example {
0% {background-color: yellow;}
50% {background: purple;}
100%{background: red;}
}
<div id="myTest"></div>
<div><button onclick="myPlayFunction(this)" class="fas fa-play"> Click this</button></div>
As you can see in my example i detect with addEventListener the finish of animation then reset animation
const myTest = document.getElementById("myTest");
function myPlayFunction(el) {
myTest.style.animationPlayState = "running";
}
myTest.addEventListener("animationend", () =>{
myTest.style.animation = 'none';
myTest.offsetHeight;
myTest.style.animation = null;
}, false);
#myTest {
width: 100px;
height: 100px;
background: red;
position: relative;
animation-name: example;
animation-duration: 3s;
animation-delay: 1s;
animation-play-state: paused;
}
#keyframes example {
0% {
background-color: yellow;
}
50% {
background: purple;
}
100% {
background: red;
}
}
<div id="myTest"></div>
<div>
<button onclick="myPlayFunction(this)" class="fas fa-play"> Click this</button>
</div>

setTimeout to JS function inside another one

I'm looking to add setTimeout to a JS function but inside this function I have another one, I'm aware that I can use onclick=setTimeout"(fooBar(), 2500);" but there's a loader inside my function, so to make it clear, I'd like to execute the function instantly (show loader div) when the button is clicked but setTimout to 2500 ms before running $.getJSON. Let's say I want to add a fake timeOut to the api request because that stuff is blazing fast.
Also, please let me know if my loading animation method with JS is ok, actually I think it's too much lines of code to show/hide div. I'm sure there's a better way to handle something like this. Thanks.
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
<title>JS Loader</title>
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css">
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
</head>
<body>
<style type="text/css" id="style">
#myloader {
position: relative;
left: 50%;
top: 50%;
z-index: 1;
width: 150px;
height: 150px;
margin: 25% -50;
border: 16px solid #000;
border-radius: 50%;
border-top: 16px solid #3498db;
width: 120px;
height: 120px;
-webkit-animation: spin 2s linear infinite;
animation: spin 2s linear infinite;
}
#-webkit-keyframes spin {
0% { -webkit-transform: rotate(0deg); }
100% { -webkit-transform: rotate(360deg); }
}
#keyframes spin {
0% { transform: rotate(0deg); }
100% { transform: rotate(360deg); }
}
/* Add animation to "page content" */
.animate-bottom {
position: relative;
-webkit-animation-name: animatebottom;
-webkit-animation-duration: 1s;
animation-name: animatebottom;
animation-duration: 1s
}
#-webkit-keyframes animatebottom {
from { bottom:-100px; opacity:0 }
to { bottom:0px; opacity:1 }
}
#keyframes animatebottom {
from{ bottom:-100px; opacity:0 }
to{ bottom:0; opacity:1 }
}
#myDiv {
display: none;
text-align: center;
}
</style>
<div class="container container-table">
<div class="row vertical-center-row">
<div class="col-md-4 col-md-offset-4">
<h1 id="name" >Real-time Bitcoin Price</h1>
<div id="myloader"style="display: none;"></div>
<p id="cointime"></p>
<div id="dollar"></div>
<div id="gbp"></div>
<div id="euro"></div><br>
<button id="refreshBtn" class="btn btn-primary">Load Data</button>
</div>
</div>
</div>
<script type="text/javascript">
document.getElementById("refreshBtn").addEventListener("click", function () {
var x = document.getElementById('myloader');
if (x.style.display === 'none') {
x.style.display = 'block';
} else {
x.style.display = 'none';
}
$.getJSON("https://api.coindesk.com/v1/bpi/currentprice.json", function (data) {
var x = document.getElementById('myloader');
if (x.style.display === 'none') {
x.style.display = 'block';
} else {
x.style.display = 'none';
}
$("#cointime").text(data.time.updated);
$("#dollar").text("USD : " + ' ' + data.bpi.USD.rate);
$("#gbp").text("GBP : " + ' ' + data.bpi.GBP.rate);
$("#euro").text("EUR :" + ' ' + data.bpi.EUR.rate);
})
});
</script>
<script src="//netdna.bootstrapcdn.com/bootstrap/3.1.1/js/bootstrap.min.js"></script>
</body>
</html>
To delay the AJAX request simply wrap the $.getJSON call in a setTimeout(). Also note that you're using an odd mix of jQuery and native JS functions. I'd suggest using one or the other, something like this:
$("#refreshBtn").on("click", function() {
$('#myloader').show();
setTimeout(function() {
$.getJSON("https://api.coindesk.com/v1/bpi/currentprice.json", function(data) {
$('#myloader').hide()
$("#cointime").text(data.time.updated);
$("#dollar").text("USD : " + ' ' + data.bpi.USD.rate);
$("#gbp").text("GBP : " + ' ' + data.bpi.GBP.rate);
$("#euro").text("EUR :" + ' ' + data.bpi.EUR.rate);
})
}, 2500);
});
#myloader {
position: relative;
left: 50%;
top: 50%;
z-index: 1;
width: 150px;
height: 150px;
margin: 25% -50;
border: 16px solid #000;
border-radius: 50%;
border-top: 16px solid #3498db;
width: 120px;
height: 120px;
-webkit-animation: spin 2s linear infinite;
animation: spin 2s linear infinite;
}
#-webkit-keyframes spin {
0% {
-webkit-transform: rotate(0deg);
}
100% {
-webkit-transform: rotate(360deg);
}
}
#keyframes spin {
0% {
transform: rotate(0deg);
}
100% {
transform: rotate(360deg);
}
}
/* Add animation to "page content" */
.animate-bottom {
position: relative;
-webkit-animation-name: animatebottom;
-webkit-animation-duration: 1s;
animation-name: animatebottom;
animation-duration: 1s
}
#-webkit-keyframes animatebottom {
from {
bottom: -100px;
opacity: 0
}
to {
bottom: 0px;
opacity: 1
}
}
#keyframes animatebottom {
from {
bottom: -100px;
opacity: 0
}
to {
bottom: 0;
opacity: 1
}
}
#myDiv {
display: none;
text-align: center;
}
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css">
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<script src="//netdna.bootstrapcdn.com/bootstrap/3.1.1/js/bootstrap.min.js"></script>
<div class="container container-table">
<div class="row vertical-center-row">
<div class="col-md-4 col-md-offset-4">
<h1 id="name">Real-time Bitcoin Price</h1>
<div id="myloader" style="display: none;"></div>
<p id="cointime"></p>
<div id="dollar"></div>
<div id="gbp"></div>
<div id="euro"></div><br>
<button id="refreshBtn" class="btn btn-primary">Load Data</button>
</div>
</div>
</div>
Also I'd suggest that adding a 2.5 second delay is far too much. I'm aware that adding a slight delay to make it more obvious that data has loaded is a good idea for UX, however I'd say that 500ms would be more than enough.
First - objects/elements:
You should always cache elements that you use more than once. Means: Assign an object to a variable that can be accessed everywhere you need it. Why? Because you can use the variable as often as you like. This saves much time and processing power because you don't need to look for an element with a certain id or class again and again. This is in my case the var x.
Second - the loader:
There are easy things like show() and hide() in jQuery, but I used ternary operation. Why? It is extremely flexible and I use it all day since I knew about it. So I want to show you this as a handy option :-).
Third - the timeout:
Pretty straight forward, wrap your function in a setTimeout() and there you go.
Here is a working fiddle:
EDIT: Now you could wrap the x.style.display lines in a separate function and call this so you can reuse the code and don't have to write it twice, but I think for demonstration purpose this should be fine.
var x = document.getElementById('myloader');
document.getElementById("refreshBtn").addEventListener("click", function () {
x.style.display = (x.style.display === 'none') ? 'block' : 'none';
setTimeout(function(){
$.getJSON("https://api.coindesk.com/v1/bpi/currentprice.json", function (data) {
x.style.display = (x.style.display === 'none') ? 'block' : 'none';
$("#cointime").text(data.time.updated);
$("#dollar").text("USD : " + ' ' + data.bpi.USD.rate);
$("#gbp").text("GBP : " + ' ' + data.bpi.GBP.rate);
$("#euro").text("EUR :" + ' ' + data.bpi.EUR.rate);
});
},2500);
});
#myloader {
position: relative;
left: 50%;
top: 50%;
z-index: 1;
width: 150px;
height: 150px;
margin: 25% -50;
border: 16px solid #000;
border-radius: 50%;
border-top: 16px solid #3498db;
width: 120px;
height: 120px;
-webkit-animation: spin 2s linear infinite;
animation: spin 2s linear infinite;
}
#-webkit-keyframes spin {
0% { -webkit-transform: rotate(0deg); }
100% { -webkit-transform: rotate(360deg); }
}
#keyframes spin {
0% { transform: rotate(0deg); }
100% { transform: rotate(360deg); }
}
/* Add animation to "page content" */
.animate-bottom {
position: relative;
-webkit-animation-name: animatebottom;
-webkit-animation-duration: 1s;
animation-name: animatebottom;
animation-duration: 1s
}
#-webkit-keyframes animatebottom {
from { bottom:-100px; opacity:0 }
to { bottom:0px; opacity:1 }
}
#keyframes animatebottom {
from{ bottom:-100px; opacity:0 }
to{ bottom:0; opacity:1 }
}
#myDiv {
display: none;
text-align: center;
}
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css">
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="container container-table">
<div class="row vertical-center-row">
<div class="col-md-4 col-md-offset-4">
<h1 id="name" >Real-time Bitcoin Price</h1>
<div id="myloader" style="display: none;"></div>
<p id="cointime"></p>
<div id="dollar"></div>
<div id="gbp"></div>
<div id="euro"></div><br>
<button id="refreshBtn" class="btn btn-primary">Load Data</button>
</div>
</div>
</div>
<script src="//netdna.bootstrapcdn.com/bootstrap/3.1.1/js/bootstrap.min.js"></script>
var timeout = null
function refresh () {
function load () {
$.getJSON('https://api.coindesk.com/v1/bpi/currentprice.json', function (data) {
$('#cointime').text(data.time.updated)
$('#dollar').text('USD : ' + data.bpi.USD.rate)
$('#gbp').text('GBP : ' + data.bpi.GBP.rate)
$('#euro').text('EUR : ' + data.bpi.EUR.rate)
timeout = null
})
}
if (timeout) {
clearTimeout(timeout)
}
timeout = setTimeout(load, 2500)
}
document.getElementById('refreshBtn').addEventListener('click', refresh)

z-index not work well in firefox

I created simple CSS3 animations but the problem that the z-index not work well in firefox, the green box must be stacked on top of the road but in the firefox browser, So I'd like to understand why this problem is appears and what is the solution?
body{
margin:0;
color:#444;
font:300 18px/18px Roboto, sans-serif;
text-align:center;
}
.element {
width: 320px;
height:100px;
position: absolute;
z-index: 50;
left: 50%;
margin-left:-160px;
top: 50%;
background-color:#00fb69;
}
#-moz-keyframes animation {
0% {
transform:scale(.95,.95) translateY(0px);
}
100% {
transform: scale(.10,.10) translateY(-800px);
}
}
#keyframes animation {
0% {
transform:scale(.95,.95) translateY(0px);
}
100% {
transform: scale(.10,.10) translateY(-800px);
}
}
.road-wrap{
-webkit-perspective:160px;
perspective:160px;
}
.road-wrap .road{
margin-top:-360px;
-webkit-transform:rotateX(80deg);
transform:rotateX(80deg);
}
.road-wrap .lane-wrap{
-webkit-animation:steer 4s linear infinite;
animation:steer 4s linear infinite;
position:relative;
z-index:-1;
}
.road-wrap .lane{
width:25px;
margin:auto;
}
.road-wrap .lane>div{
width:100%;
margin:auto;
margin-top:30px;
margin-bottom:30px;
position:relative;
background-color:#444;
-webkit-animation:lane 10s linear reverse infinite;
animation:lane 10s linear reverse infinite;
}
.road-wrap .lane>div:nth-child(1){height:15px}
.road-wrap .lane>div:nth-child(2){height:20px}
.road-wrap .lane>div:nth-child(3){height:30px}
.road-wrap .lane>div:nth-child(4){height:50px}
.road-wrap .lane>div:nth-child(5){height:40px}
.road-wrap .lane>div:nth-child(6){height:50px}
.road-wrap .lane>div:nth-child(7){height:40px}
.road-wrap .lane>div:nth-child(8){height:50px}
.road-wrap .lane>div:nth-child(9){height:30px}
.road-wrap .lane>div:nth-child(10){height:20px}
.road-wrap .lane>div:nth-child(11){height:15px}
#-webkit-keyframes lane{
0%{
-webkit-transform:translateY(320px);
transform:translateY(320px);
}
100%{
-webkit-transform:translateY(-160px);
transform:translateY(-160px);
}
}
#keyframes lane{
0%{
-webkit-transform:translateY(320px) scale(.60,.60);
transform:translateY(320px) scale(.60,.60);
}
100%{
-webkit-transform:translateY(-160px) scale(.80,.80);
transform:translateY(-160px) scale(.80,.80);
}
}
#media(max-width:768px) {
.element{
width:150px;
margin-left:-75px;
}
}
#media (min-width: 768px){
.element{
width:250px;
margin-left:-125px;
}
}
<div class="loading-screen">
<div class="element">
</div>
<div class="road-wrap">
<div class="road">
<div class="lane-wrap">
<div class="lane">
<div></div>
<div></div>
<div></div>
<div></div>
<div></div>
<div></div>
<div></div>
<div></div>
<div></div>
<div></div>
<div></div>
</div>
</div>
</div>
</div>
</div>
Just place <div class="element"> after <div class="road-wrap"> in the code.
You can find your script fix at the following link.
https://jsfiddle.net/w42fqb5e/1/
Basically you need to change the order of your divs in the HTML.
Notes: I tested this solution on FF 53.0 (32-bit) WIN.
<div class="loading-screen">
<div class="road-wrap">
<div class="road">
<div class="lane-wrap">
<div class="lane">
<div></div>
<div></div>
<div></div>
<div></div>
<div></div>
<div></div>
<div></div>
<div></div>
<div></div>
<div></div>
<div></div>
</div>
</div>
</div>
</div>
<div class="element">
</div>
</div>
For a real solution, you should probably report this to Mozilla's bugzilla.
It's quite hard to debug, but I tried to pause the animation as soon as I saw the effect, and obviously, when the animation stopped, everything was back to normal on screen...
For the ones interested, here is the fiddle where I lost a few dozens of minutes trying to capture the bug (could be a good game b.t.w).
Now, since I guess you are willing for a workaround, well... I may have a js one.
Since I think we identified that the animation is the problem, where I feel the little panda takes a nap in the middle of the rendering, we just have to tell it to never sleep.
And to do so, we can constantly request for a reflow of our .element, by simply calling one of its offsetXXX properties.
Beware, since the bug occurs only sporadically on my machine, I can't tell for sure that this workaround actually works 100% of the time. So be kind, tell me in comments if it failed for you.
// forces a reflow at every frame
const element = document.querySelector('.element');
const anim = t => {
element.offsetLeft;
requestAnimationFrame(anim)
}
anim();
// forces a reflow at every frame
const element = document.querySelector('.element');
const anim = t => {
element.offsetLeft;
requestAnimationFrame(anim)
}
anim();
body{
margin:0;
color:#444;
font:300 18px/18px Roboto, sans-serif;
text-align:center;
}
.element {
width: 320px;
height:100px;
position: absolute;
z-index: 50;
left: 50%;
margin-left:-160px;
top: 50%;
background-color:#00fb69;
}
#-moz-keyframes animation {
0% {
transform:scale(.95,.95) translateY(0px);
}
100% {
transform: scale(.10,.10) translateY(-800px);
}
}
#keyframes animation {
0% {
transform:scale(.95,.95) translateY(0px);
}
100% {
transform: scale(.10,.10) translateY(-800px);
}
}
.road-wrap{
-webkit-perspective:160px;
perspective:160px;
}
.road-wrap .road{
margin-top:-360px;
-webkit-transform:rotateX(80deg);
transform:rotateX(80deg);
}
.road-wrap .lane-wrap{
-webkit-animation:steer 4s linear infinite;
animation:steer 4s linear infinite;
position:relative;
z-index:-1;
}
.road-wrap .lane{
width:25px;
margin:auto;
}
.road-wrap .lane>div{
width:100%;
margin:auto;
margin-top:30px;
margin-bottom:30px;
position:relative;
background-color:#444;
-webkit-animation:lane 10s linear reverse infinite;
animation:lane 10s linear reverse infinite;
}
.road-wrap .lane>div:nth-child(1){height:15px}
.road-wrap .lane>div:nth-child(2){height:20px}
.road-wrap .lane>div:nth-child(3){height:30px}
.road-wrap .lane>div:nth-child(4){height:50px}
.road-wrap .lane>div:nth-child(5){height:40px}
.road-wrap .lane>div:nth-child(6){height:50px}
.road-wrap .lane>div:nth-child(7){height:40px}
.road-wrap .lane>div:nth-child(8){height:50px}
.road-wrap .lane>div:nth-child(9){height:30px}
.road-wrap .lane>div:nth-child(10){height:20px}
.road-wrap .lane>div:nth-child(11){height:15px}
#-webkit-keyframes lane{
0%{
-webkit-transform:translateY(320px);
transform:translateY(320px);
}
100%{
-webkit-transform:translateY(-160px);
transform:translateY(-160px);
}
}
#keyframes lane{
0%{
-webkit-transform:translateY(320px) scale(.60,.60);
transform:translateY(320px) scale(.60,.60);
}
100%{
-webkit-transform:translateY(-160px) scale(.80,.80);
transform:translateY(-160px) scale(.80,.80);
}
}
#media(max-width:768px) {
.element{
width:150px;
margin-left:-75px;
}
}
#media (min-width: 768px){
.element{
width:250px;
margin-left:-125px;
}
}
<div class="loading-screen">
<div class="element">
</div>
<div class="road-wrap">
<div class="road">
<div class="lane-wrap">
<div class="lane">
<div></div>
<div></div>
<div></div>
<div></div>
<div></div>
<div></div>
<div></div>
<div></div>
<div></div>
<div></div>
<div></div>
</div>
</div>
</div>
</div>
</div>
And as a fiddle.

CSS Animation onClick

How can I get a CSS Animation to play with a JavaScript onClick? I currently have:
.classname {
-webkit-animation-name: cssAnimation;
-webkit-animation-duration:3s;
-webkit-animation-iteration-count: 1;
-webkit-animation-timing-function: ease;
-webkit-animation-fill-mode: forwards;
}
#-webkit-keyframes cssAnimation {
from {
-webkit-transform: rotate(0deg) scale(1) skew(0deg) translate(100px);
}
to {
-webkit-transform: rotate(0deg) scale(2) skew(0deg) translate(100px);
}
}
How can I apply an onClick?
Are you sure you only display your page on webkit? Here is the code, passed on safari.
The image (id='img') will rotate after button click.
function ani() {
document.getElementById('img').className = 'classname';
}
.classname {
-webkit-animation-name: cssAnimation;
-webkit-animation-duration: 3s;
-webkit-animation-iteration-count: 1;
-webkit-animation-timing-function: ease;
-webkit-animation-fill-mode: forwards;
}
#-webkit-keyframes cssAnimation {
from {
-webkit-transform: rotate(0deg) scale(1) skew(0deg) translate(100px);
}
to {
-webkit-transform: rotate(0deg) scale(2) skew(0deg) translate(100px);
}
}
<input name="" type="button" onclick="ani()" value="Click">
<img id="img" src="https://i.stack.imgur.com/vghKS.png" width="328" height="328" />
You just use the :active pseudo-class. This is set when you click on any element.
.classname:active {
/* animation css */
}
Found solution on css-tricks
const element = document.getElementById('img')
element.classList.remove('classname'); // reset animation
void element.offsetWidth; // trigger reflow
element.classList.add('classname'); // start animation
You can achieve this by binding an onclick listener and then adding the animate class like this:
$('#button').onClick(function(){
$('#target_element').addClass('animate_class_name');
});
CSS ONLY solution that works on every click and plays the animation to the end:
All you have to do is to add the animation to the :focus pseudo class and set it to none in :active pseudo class.
If your element isn't focusable add tabindex="0" attribute to the html element:
#keyframes beat {
0% {
-webkit-transform: scale(1, 1);
transform: scale(1, 1);
}
100% {
-webkit-transform: scale(0.8,0.8);
transform: scale(0.8, 0.8);
}
}
.className {
background-color:#07d;
color: #fff;
font-family: sans-serif;
font-size: 20px;
padding: 20px;
margin:5px;
-webkit-transform: scale(1, 1);
transform: scale(1, 1);
}
.className:focus {
-webkit-animation: beat 1s ease-in-out backwards;
animation: beat 1s ease-in-out backwards;
}
.className:active {
-webkit-animation: none;
animation: none;
}
body {
text-align: center;
}
<h3>Any element with tabindex="0", like a div:</h3>
<div tabindex="0" class="className"> Click me many times!</div>
<h3>Any focusable element like a button:</h3>
<button class="className"> Click me many times!</button>
var abox = document.getElementsByClassName("box")[0];
function allmove(){
abox.classList.remove("move-ltr");
abox.classList.remove("move-ttb");
abox.classList.toggle("move");
}
function ltr(){
abox.classList.remove("move");
abox.classList.remove("move-ttb");
abox.classList.toggle("move-ltr");
}
function ttb(){
abox.classList.remove("move-ltr");
abox.classList.remove("move");
abox.classList.toggle("move-ttb");
}
.box {
width: 100px;
height: 100px;
background: red;
position: relative;
}
.move{
-webkit-animation: moveall 5s;
animation: moveall 5s;
}
.move-ltr{
-webkit-animation: moveltr 5s;
animation: moveltr 5s;
}
.move-ttb{
-webkit-animation: movettb 5s;
animation: movettb 5s;
}
#keyframes moveall {
0% {left: 0px; top: 0px;}
25% {left: 200px; top: 0px;}
50% {left: 200px; top: 200px;}
75% {left: 0px; top: 200px;}
100% {left: 0px; top: 0px;}
}
#keyframes moveltr {
0% { left: 0px; top: 0px;}
50% {left: 200px; top: 0px;}
100% {left: 0px; top: 0px;}
}
#keyframes movettb {
0% {left: 0px; top: 0px;}
50% {top: 200px;left: 0px;}
100% {left: 0px; top: 0px;}
}
<div class="box"></div>
<button onclick="allmove()">click</button>
<button onclick="ltr()">click</button>
<button onclick="ttb()">click</button>
Add a
-webkit-animation-play-state: paused;
to your CSS file, then you can control whether the animation is running or not by using this JS line:
document.getElementById("myDIV").style.WebkitAnimationPlayState = "running";
if you want the animation to run once, every time you click. Remember to set
-webkit-animation-iteration-count: 1;
You can do that by using following code
$('#button_id').on('click', function(){
$('#element_want_to_target').addClass('.animation_class');});
Try this:
<div>
<p onclick="startAnimation()">Start</p><!--O botão para iniciar (start)-->
<div id="animation">Hello!</div> <!--O elemento que você quer animar-->
</div>
<style>
#keyframes animationName {
from {margin-left:-30%;}
}
</style>
<script>
function startAnimation() {
document.getElementById("animation").style.animation = "animationName 2s linear 1";
}
</script>
Add the animation and remove it after the animation-duration ends using setTimeout()
const elem = document.querySelector(".element");
elem.onclick = () => {
elem.style.animation="YOUR_ANIMATION";
setTimeout(()=>{
elem.style.animation="none";
},YOUR_ANIMATION_DURATION);
}

Categories

Resources