The following setup (see below) animates the div on page load using jQuery, but fails in vanilla JavaScript, in that it gives me the animated state without the animation. I don't wand to use keyframes or a delay, and nothing I tried in JS worked.
Here's the working version, with jQuery:
jQuery(function($) {
$(document).ready(function() {
$("#new-selector").addClass("animated-selector");
});
});
#new-selector {
background: #3a88fe;
width: 50px;
height: 50px;
transition: transform 500ms ease;
}
#new-selector.animated-selector {
background: orange;
transform: translate(75px, 20px) scale(1.5);
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div id="new-selector"></div>
Here's the problematic version, with vanilla JS:
document.addEventListener('DOMContentLoaded', function() {
document.getElementById('new-selector').classList.add('animated-selector');
});
#new-selector {
background: #3a88fe;
width: 50px;
height: 50px;
transition: transform 500ms ease;
}
#new-selector.animated-selector {
background: orange;
transform: translate(75px, 20px) scale(1.5);
}
<div id="new-selector"></div>
For the vanilla JS version you might need to wait for the browser to give you the next animation frame using requestAnimationFrame:
document.addEventListener('DOMContentLoaded', function() {
requestAnimationFrame(() => document.getElementById('new-selector').classList.add('animated-selector'))
});
#new-selector {
background: #3a88fe;
width: 50px;
height: 50px;
transition: transform 500ms ease;
}
#new-selector.animated-selector {
background: orange;
transform: translate(75px, 20px) scale(1.5);
}
<div id="new-selector"></div>
Related
I have a button. I want to add to this button class: space and after this class was added and is visible in browser I want to add another class: spinner
I have tried with:
$("button").on("click", function(){
$(this).addClass("space");
$(this).addClass("spinner");
}
CSS:
.spacer{
transition: .3s !important;
padding-right: 3.1rem !important;
}
.spinner{
border: 5px solid #f3f3f3;
border-radius: 50%;
border-top: 5px solid #3498db;
width: 10px;
height: 10px;
animation: spin 2s linear infinite;
}
But it, obviously, doesn't work. Why?
Can a class be added to an element only after a class was added and has made its effect?
you could add the second class with a short timeout.this gives you also the possibility to add some animations if needed.
window.setTimeout(function() {
button.addClass("spinner");
},500);
promises will work to
You can add event listener to check if the transition is completed.
Consider the code below:
var el = document.getElementById('someelement');
debugger;
function transitionCallback(){
var t;
var transitions = {
'transition':'transitionend',
'OTransition':'oTransitionEnd',
'MozTransition':'transitionend',
'WebkitTransition':'webkitTransitionEnd'
}
for(t in transitions){
if( el.style[t] !== undefined ){
return transitions[t];
}
}
}
/* Listen for transition */
var transitionEvent = transitionCallback();
transitionEvent && el.addEventListener(transitionEvent, function() {
console.log('Transition complete.');
});
/*transition example is from w3schools*/
#someelement {
width: 100px;
height: 100px;
background: red;
transition: width 2s;
-webkit-transition: width 2s; /* Safari 3.1 to 6.0 */
}
#someelement:hover {
width: 300px;
}
<html>
<head>
</head>
<body>
<div id="someelement"></div>
</body>
</html>
Use animation-delay to set a delay before it starts to run. I set it to a big number just so you can see the delay.
document.querySelector('button')
.addEventListener('click', event => {
event.preventDefault()
const classList = event.target.classList
classList.toggle('spacer')
classList.toggle('spinner')
})
.spacer{
transition: .3s !important;
padding-right: 3.1rem !important;
}
.spinner{
border: 5px solid #f3f3f3;
border-radius: 50%;
border-top: 5px solid #3498db;
width: 10px;
height: 10px;
animation: spin 2s linear infinite;
animation-delay: 2s;
}
#keyframes spin {
0% { transform: rotate(0deg); }
100% { transform: rotate(360deg); }
}
<button></button>
I don't know how to use JQuery, so I need a method which could trigger an animation using JavaScript only.
I need to call/trigger CSS Animation when the user scrolls the page.
function start() {
document.getElementById('logo').style.animation = "anim 2s 2s forward";
document.getElementById('earthlogo').style.animation = "anim2 2s 2s forward";
}
* {
margin: 0px;
}
#logo {
position: fixed;
top: 200px;
height: 200px;
width: 1000px;
left: 5%;
z-index: 4;
opacity: 0.8;
}
#earthlogo {
position: fixed;
top: 200px;
height: 120px;
align-self: center;
left: 5%;
margin-left: 870px;
margin-top: 60px;
z-index: 4;
opacity: 0.9;
}
#keyframes anim {
50% {
filter: blur(10px);
transform: rotate(-15deg);
box-shadow: 0px 0px 10px 3px;
}
100% {
height: 100px;
width: 500px;
left: 10px;
top: 10px;
box-shadow: 0px 0px 15px 5px rgba(0, 0, 0, 0.7);
background-color: rgba(0, 0, 1, 0.3);
opacity: 0.7;
}
}
#keyframes anim2 {
50% {
filter: blur(40px);
transform: rotate(-15deg);
}
100% {
height: 60px;
width: 60px;
left: 10px;
top: 10px;
margin-left: 435px;
margin-top: 30px;
opacity: 0.8;
}
}
#backstar {
position: fixed;
width: 100%;
z-index: 1;
}
#earth {
position: absolute;
width: 100%;
z-index: 2;
top: 300px;
}
<img src="logo.png" id="logo" onclick="start();">
<img src="earthlogo.gif" id="earthlogo" onscroll="start();">
<img src="earth.png" id="earth">
<img src="stars.jpg" id="backstar">
The simplest method to trigger CSS animations is by adding or removing a class - how to do this with pure Javascript you can read here:
How do I add a class to a given element?
If you DO use jQuery (which should really be easy to learn in basic usage) you do it simply with addClass / removeClass.
All you have to do then is set a transition to a given element like this:
.el {
width:10px;
transition: all 2s;
}
And then change its state if the element has a class:
.el.addedclass {
width:20px;
}
Note: This example was with transition. But for animations its the same: Just add the animation on the element which has a class on it.
There is a similar question here: Trigger a CSS keyframe animation via scroll
This is how you can use vanilla JavaScript to change/trigger an animation associated with an HTML element.
First, you define your animations in CSS.
#keyframes spin1 { 100% { transform:rotate(360deg); } }
#keyframes spin2 { 100% { transform:rotate(-360deg); } }
#keyframes idle { 100% {} }
Then you use javascript to switch between animations.
document.getElementById('yourElement').style.animation="spin2 4s linear infinite";
Note: 'yourElement' is the target HTML element that you wish to
animate.
For example: <div id="yourElement"> ... </div>
Adding and removing the animation class does not work in a function. The delay is simply too little. As suggested by this article you can request the browser to reflow and then add the class. The delay isn't an issue in that case. Hence, you can use this code:
element.classList.remove("animation")
element.offsetWidth
element.classList.add("animation")
The best thing is, this works everywhere. All credit goes to the article.
A more idiomatic solution is to use the Web Animations API.
Here is the example from MDN:
document.getElementById("alice").animate(
[
{ transform: 'rotate(0) translate3D(-50%, -50%, 0)', color: '#000' },
{ color: '#431236', offset: 0.3 },
{ transform: 'rotate(360deg) translate3D(-50%, -50%, 0)', color: '#000' }
], {
duration: 3000,
iterations: Infinity
}
);
OP's example:
document.getElementById('logo').animate(
[
{},
{
filter: 'blur(10px)',
transform: 'rotate(-15deg)',
box-shadow: '0px 0px 10px 3px',
},
{
height: '100px',
width: '500px',
left: '10px',
top: '10px',
box-shadow: '0px 0px 15px 5px rgba(0, 0, 0, 0.7)',
background-color: 'rgba(0, 0, 1, 0.3)',
opacity: '0.7',
},
],
{
duration: 2000,
delay: 2000,
fill: 'forwards',
},
)
At the time of writing, it's supported in all major browsers except IE.
Supported browsers
I have a similar problem.
The best answer didn’t work for me, but when I added the delay it worked.
The following is my solution.
CSS
.circle_ani1,
.circle_ani2 {
animation-duration: 1s;
animation-iteration-count: 1;
}
.circle_ani1 {
animation-name: circle1;
}
.circle_ani2 {
animation-name: circle2;
}
JS
let temp_circle1 = $('.TimeCountdown_circle1').removeClass('circle_ani1');
let temp_circle2 = $('.TimeCountdown_circle2').removeClass('circle_ani2');
window.setTimeout(function() {
temp_circle1.addClass('circle_ani1');
temp_circle2.addClass('circle_ani2');
}, 50);
Vanilla JS version
document.getElementById('logo').classList.add("anim");
document.getElementById('earthlogo').classList.add("anim2");
You could use CSS to hide the image / animation and show when the user scrolls. This would work like this:
CSS:
div {
border: 1px solid black;
width: 200px;
height: 100px;
overflow: scroll;
}
#demo{
display: none;
}
HTML:
<div id="myDIV"> </div>
<div id="demo">
<img src="earthlogo.gif" id="earthlogo" alt="Thanks for scrolling. Now you see me">
</div>
Your javascript just needs to include an eventListener to call the function which triggers the display of your animation.
JS:
document.getElementById("myDIV").addEventListener("scroll", start);
function start() {
document.getElementById('demo').style.display='block';
}
You could use animation-play-state (Mdn docs) like this
element.style.animationPlayState = "paused/running"
Code snippet:
function play() {
document.getElementById("div").style.animationPlayState = "running";
}
function pause() {
document.getElementById("div").style.animationPlayState = "paused";
}
.animation {
width: 50px;
height: 50px;
background-color: red;
position: relative;
animation-name: example;
animation-duration: 2s;
animation-play-state: paused;
animation-iteration-count: infinite;
}
#keyframes example {
0% {
background-color: red;
left: 0px;
top: 0px;
}
25% {
background-color: yellow;
left: 50px;
top: 0px;
}
50% {
background-color: blue;
left: 50px;
top: 50px;
}
75% {
background-color: green;
left: 0px;
top: 50px;
}
100% {
background-color: red;
left: 0px;
top: 0px;
}
}
<button onclick="play()">Play</button>
<button onclick="pause()">Pause</button><br><br>
<div id="div" class="animation"></div>
Here's the main code:
HTML:
<img id="myImg">
CSS:
#myImg {
//properties
animation: animate 2s linear infinite //infinite is important!
}
#keyframes animate {
//animation base
}
JS:
document.getElementById("myImg").style.webkitAnimationPlayState = "paused";
window.addEventListener("scroll", function() {
document.getElementById("myImg").style.webkitAnimationPlayState = "running";
setTimeout(function() {
document.getElementById("myImg").style.webkitAnimationPlayState = "paused";
}, 2000);
});
If you want Animations i recommend you create a CSS class which you toggle on a Condition whit JS:
CSS
.animation {
animation: anim 2s ease infinite;
transition: .2s
}
JS
// Select your Element
$element.document.querySelector(".yourElement");
$element.addEventListner('click', () => {
$element.classList.toggle("animation")
})
I have a keyframe animation which plays when I hover on element. After the mouseout event, it stops too abruptly. How could I force it play till it's end? I tried on.(animationend) event, it doesn't work. Transform origin and huge delay, either don't work. Thanks.
CodePen Demo
class Main {
constructor() {
}
waveOn() {
$(this).addClass('wave-active');
}
waveOut() {
var elem = $('.info__block');
elem.removeClass('wave-active');
}
jsInit() {
$('.info__block').hover(this.waveOn);
$('.info__block').on('animationend', this.waveOut)
}
}
new Main().jsInit();
.info__block {
width: 100px;
height: 100px;
background: aqua;
border-radius: 50px;
position: relative;
display: flex;
justify-content: center;
margin-top: 100px;
}
.info__block:before {
content: '';
position: absolute;
width: 100%;
height: 100%;
border-radius: 50px;
border-top: 2px solid aqua;
}
.info__block.wave-active:before {
animation: link-line 2.5s infinite .5s linear;
}
#keyframes link-line {
0% {
transform: translateY(0);
opacity: 1;
}
60% {
opacity: 0;
}
100% {
transform: translateY(-50%) scale(1.6);
opacity: 0;
}
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="info__block info__block-1">
</div>
Here is a solution to your problem using the native animationiteration event that is described in the W3C Spec for animations. This event is fired after every single iteration of the animation. So, what we are doing is that on hover out, we are attaching the animationiteration event listener (which will get fired only once due to the one). Within this event's listener, I've simply placed the contents of original waveOut function. So, everytime you hover the mouse out of the element, the animation will complete one single iteration (after the hover out has happened) and then stop with that. I think this is a lot more graceful than an abrupt end.
class Main {
constructor() {}
jsInit() {
$('.info__block').hover(function() {
$('.info__block').off('animationiteration'); /* switch off the event handler when you quickly hover back in again */
$('.info__block').addClass('wave-active');
}, function() {
$('.info__block').one('animationiteration', function() {
$('.info__block').removeClass('wave-active');
})
});
}
}
new Main().jsInit();
body {
padding: 200px 200px;
}
.info__block {
width: 100px;
height: 100px;
background: aqua;
border-radius: 50px;
position: relative;
display: flex;
justify-content: center;
}
.info__block:before {
content: '';
position: absolute;
width: 100%;
height: 100%;
border-radius: 50px;
border-top: 2px solid aqua;
}
.info__block.wave-active:before {
animation: link-line 2.5s infinite .5s linear;
}
#keyframes link-line {
0% {
transform: translateY(0);
opacity: 1;
}
60% {
opacity: 0;
}
100% {
transform: translateY(-50%) scale(1.6);
opacity: 0;
}
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="info__block info__block-1">
</div>
(Note: In the above demo sometimes the animation stops after just one iteration during the second and subsequent hover operations. This seems to be some glitch with the Run Snippet window. I don't see this problem happening in the Editor's output window or in this CodePen demo. If you also encounter the same problem let me know and I'll see if there is any fix for it.)
Note: The problem mentioned above has been fixed and the snippet is also updated with the revised code. Revised CodePen Demo.
An infinite animation doesn't have animationend event.
I'm want to disable all css transitions using JavaScript. I added transition: none to the body (via JavaScript), but the elements in the body still have a transition.
Of course I can loop through all elements, and add transition = 'none';, but I'm sure there's a better way of temporary disabling the css transition of all elements. Here's a sample code:
JSFiddle
var sample = document.getElementById('sample');
sample.addEventListener('click', function() {
if (document.body.style.transition === 'none') {
document.body.style.transition = '';
} else {
document.body.style.transition = 'none';
}
})
#sample {
width: 200px;
height: 100px;
background: lawngreen;
transition: transform 500ms ease;
}
#sample:hover {
transform: translateX(50px);
}
<div id="sample">Hover over me to move
<br />Click to disable transition</div>
Add a new class name to the body or parent tag. Set transitions with the new parent selector .animated #sample:
<body class="animated">
<div id="sample"></div>
</body>
... and the styles:
#sample {
width: 200px;
height: 100px;
background: lawngreen;
}
.animated #sample {
transition: transform 500ms ease;
}
.animated #sample:hover {
transform: translateX(50px);
}
To disable animations of all children just remove the .animated class from the body or parent tag.
Modified fiddle: https://jsfiddle.net/xjxauu0h/1/
you'll want to use a class on body so you can turn it on and off.
var sample = document.getElementById('sample');
document.body.classList.add('transitioner');
sample.addEventListener('click', function() {
if (document.body.classList && document.body.classList.length) {
document.body.classList.remove('transitioner');
} else {
document.body.classList.add('transitioner');
}
console.log(document.body.classList);
})
#sample {
width: 200px;
height: 100px;
background: lawngreen;
}
.transitioner *{
transition: transform 500ms ease;
}
#sample:hover {
transform: translateX(50px);
}
<div id="sample">Hover over me to move
<br />Click to disable transition</div>
var sample = $('#sample');
var body = $('body');
sample.click(function() {
body.toggleClass('notransition notransform');
});
#sample {
width: 200px;
height: 100px;
background: lawngreen;
transition: transform 500ms ease;
}
#sample:hover {
transform: translateX(50px);
}
.notransition.notransform #sample {
background: HotPink;
}
.notransition * {
-webkit-transition: none !important;
-moz-transition: none !important;
-o-transition: none !important;
-ms-transition: none !important;
transition: none !important;
}
.notransform * {
-webkit-transform: none !important;
-moz-transform: none !important;
-o-transform: none !important;
-ms-transform: none !important;
transform: none !important;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div id="sample">Hover over me to move
<br />Click to disable transition</div>
For some reason when I add the second click function it stops working completely. I was wondering if anybody could help pin point what the issue might be?
What I'm trying to do:
The default state is "day" and when "night" is clicked, it removes the day class and adds the night class. Which changes the background image. Which works... Sort of. However, when I add the function for the day button to add the day class and remove the night class is breaks and doesn't work.
Here's a fiddle of what I have: http://jsfiddle.net/790hqykq/3/
$(document).ready(function () {
$('.night').click(function () {
$('#room').addClass('night');
$('#room').removeClass('day');
});
$('.day').click(function () {
$('#room').addClass('day');
$('#room').removeClass('night');
});
});
Thanks!!
Edit: Also - Is there any way to fade this class change? Similar to fadeIn/fadeOut? Thanks!
jsFiddle Demo
The problem with your fiddle is that the #room element has the class day. So does the anchor element. When the event handler is setup
$('.day').click(function () {
It is also assigned to the room element, and as a result of that, #room ends up also having the event handler attached to it. This causes day to always be selected as the element's class, even when night is clicked.
You should consider changing the class name to something like daycolor and nightcolor
<div id="room" class="daycolor">
and
#room.daycolor {
background: #00CCFF;
}
The element with ID room has the class day, as one of the elements within it.
When you attach the handler, it's being attached to both elements.
This should solve your problem:
$(document).ready(function () {
$('.timeButton.day').click(function () {
$('#room').addClass('day').removeClass('night');
});
$('.timeButton.night').click(function () {
$('#room').addClass('night').removeClass('day');
});
});
As per your complement about fading, you can use CSS 3 to achieve this:
#room {
-webkit-transition: background 0.5s linear;
-moz-transition: background 0.5s linear;
-ms-transition: background 0.5s linear;
-o-transition: background 0.5s linear;
transition: background 0.5s linear;
}
Demo
Change the classnames on your children elements and use that selector for your events.
jsFiddle
HTML:
<div id="container">
<div id="room" class="day">
<a class="timeButton day1">Day</a>
<a class="timeButton night1">Night</a>
</div>
</div>
JS:
$(document).ready(function () {
$('.night1').click(function () {
$('#room').addClass('night');
$('#room').removeClass('day');
});
$('.day1').click(function () {
$('#room').addClass('day');
$('#room').removeClass('night');
});
});
Style:
#container {
width: 300px;
margin: 0 auto;
}
#container a, #container div {
float: left;
display: block;
}
#room {
width: 300px;
height: 200px;
position: relative;
}
#room.day {
background: #00CCFF;
}
#room.night {
background: #0000CC;
}
#room .day1 {
left: 30px;
border: 1px solid black;
}
#room .night1 {
right: 30px;
border: 1px solid black;
}
#room .timeButton {
position: absolute;
width: 80px;
height: 25px;
top: 30px;
cursor: pointer;
text-align: center;
}
#room .timeButton:hover {
background: #fff;
}
Here is another solution, where I just change the css-style via jquery.
Javascript:
$(document).ready(function () {
$('.day').click(function () {
$('#room').css("background-color", "#00CCFF");
});
$('.night').click(function () {
$('#room').css("background-color", "#0000CC");
});
});
Also you need to add a background-color to #room:
background: #00CCFF;
Fiddle:
http://jsfiddle.net/790hqykq/7/
In your script, you reference to ".night" instead ".nightButton".
$('.nightButton').click(function () {
$('#room').addClass('night');
$('#room').removeClass('day');
});
$('.dayButton').click(function () {
$('#room').addClass('day');
$('#room').removeClass('night');
});
To achieve the transition, you can add this CSS propertie to #room.
-webkit-transition: background 2s; /* For Safari 3.1 to 6.0 */
transition: background 2s;
http://jsfiddle.net/790hqykq/13/
you can add css3 for the transitions from day to night.
it wont working in older IE browsers 9 and under but is excellent in all modern browsers.
browser support. You can use this generator to make the code faster.
#room {
width: 300px;
height: 200px;
position: relative;
-webkit-transition: background 1000ms ease-in-out;
-moz-transition: background 1000ms ease-in-out;
-ms-transition: background 1000ms ease-in-out;
-o-transition: background 1000ms ease-in-out;
transition: background 1000ms ease-in-out;
}
Demo jsfiddle