I want that whenever I click on the div, it first translate, then rotate and, finally scale. Further, I want to reverse it back in the same way when I click again
I have the following code:
$(() => {
$('div').on('click', () => {
$('div').toggleClass('clicked');
});
});
div.normal {
height: 20px;
width: 100px;
background: black;
transition: 2s all;
}
div.clicked {
transform: translate(100px, 100px) rotate(45deg) scale(2);
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class='normal'></div>
As you can see, all the transformations are occurring at the same time. But, I want them to occur separately. How do I achieve this?
Thanks in advance!
Decompose your animation using keyframes. Here is a minimally edited version of your code:
var $el = $('#to-animate')
var firstClick = true
$el.click(() => {
$el.toggleClass('clicked')
if (!firstClick) {
$el.toggleClass('unclicked')
}
firstClick = false
})
div.normal {
height: 20px;
width: 100px;
background: black;
}
div.clicked {
animation: transforms 2s forwards;
}
div.unclicked {
animation: transforms-2 2s reverse;
}
#keyframes transforms {
33% {
transform: translate(100px, 100px);
}
66% {
transform: translate(100px, 100px) rotate(45deg);
}
100% {
transform: translate(100px, 100px) rotate(45deg) scale(2);
}
}
#keyframes transforms-2 {
33% {
transform: translate(100px, 100px);
}
66% {
transform: translate(100px, 100px) rotate(45deg);
}
100% {
transform: translate(100px, 100px) rotate(45deg) scale(2);
}
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div id="to-animate" class='normal'></div>
Edit updated to include ability to reverse the animation (making the code edit less minimal)
An idea is to rely on other properties to achieve the same effect and be able to apply different transition
$(() => {
$('div').on('click', () => {
$('div').toggleClass('clicked');
});
});
div.normal {
height: calc(20px * var(--s,1));
width: calc(100px * var(--s,1));
background: black;
position:relative;
top:0;
left:0;
transition: 2s top 4s,2s left 4s,2s width 2s,2s height 2s,2s transform;
}
div.clicked {
top:100px;
left:100px;
--s:2;
transform:rotate(45deg);
transition: 2s top,2s left,2s width 2s,2s height 2s,2s transform 4s;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class='normal'></div>
Related
The snippet below shows a spinning circle. Every 1 second I want this circle to double in size and then shrink back to it's original size(to look like a heartbeat). The way I am attempting to do this is by creating a timer in javascript so that every one second, the class which causes the grow effect is removed from the circle, and then immediately added back on. I was hoping that having the class added back on after being removed would trigger the animation but I guess not. Right now the "heartbeat" only happens once.
Also I would like to have the circle spinning at constant speed if that's possible. Right now the circle really slows down at the end, and starts a little bit slow.
// set timeout
let tid = setTimeout(mycode, 1000);
function mycode() {
// do some stuff...
let ic = document.getElementById('inner-circle')
ic.classList.remove('heartbeat')
ic.classList.add('heartbeat')
tid = setTimeout(mycode, 1000); // repeat myself
}
function abortTimer() { // to be called when you want to stop the timer
clearTimeout(tid);
}
#spinning-circle {
animation-name: spinning-circle;
animation-duration: 10s;
animation-iteration-count: infinite;
width: 40px;
height: 40px;
}
.heartbeat {
width: 100%;
height: 100%;
animation-name: heartbeat;
animation-duration: 0.15s;
animation-iteration-count: 2;
animation-direction: alternate;
animation-fill-mode: both;
}
#inner-circle img {
width: 100%;
height: auto;
}
#-webkit-keyframes heartbeat {
100% {
transform: scale(2,2);
-webkit-transform: scale(2,2);
}
}
#-webkit-keyframes spinning-circle {
0% {
-webkit-transform: rotate(0deg);
transform: rotate(0deg);
}
100% {
-webkit-transform: rotate(360deg);
transform: rotate(360deg);
}
}
<div id="spinning-circle">
<div id='inner-circle'>
<img src="http://i.stack.imgur.com/WbNlQ.jpg">
</div>
</div>
use setInterval() and clearInterval() instead of setTimeout(), and remove the setTimeout() inside the function mycode()
// set timeout
let tid = setInterval(mycode, 1000);
function mycode() {
// do some stuff...
let ic = document.getElementById('inner-circle')
ic.classList.remove('heartbeat')
ic.classList.add('heartbeat')
}
function abortTimer() { // to be called when you want to stop the timer
clearInterval(tid);
}
and for the animation speed add animation-timing-function: linear; to .heartbeat {} and #spinning-circle {}
You don't need javascript at all:
#spinning-circle {
margin-top: 40px;
margin-left: 40px;
animation: spinning-circle linear 10s infinite;
width: 40px;
height: 40px;
overflow: visible;
}
#inner-circle {
animation: heartbeat 1s infinite;
}
#inner-circle img {
width: 100%;
height: auto;
}
#keyframes heartbeat {
0% {
transform: scale(1);
}
25% {
transform: scale(2);
}
50% {
transform: scale(1);
}
100% {
transform: scale(1);
}
}
#keyframes spinning-circle {
0% {
transform: rotate(0turn);
}
100% {
transform: rotate(-1turn);
}
}
<div id="spinning-circle">
<div id='inner-circle'>
<img src="http://i.stack.imgur.com/WbNlQ.jpg">
</div>
</div>
I have a balloon that when hovered, will expand n disappear (a popping-like animation). I made this in CSS but when the cursor moves, the balloon returned. I want the balloon to disappear forever until I refresh the page, so I guess it needs to be onclick, but that selector is not available in CSS.
Here's what I have in CSS
#keyframes pop
{
from{
opacity:1;
transform: translateZ(0) scale(1,1);
}
to{
opacity:0;
transform: translateZ(0) scale(1.5,1.5);
}
}
.balloon:hover
{
animation: pop 0.5s cubic-bezier(0.16, 0.87, 0.48, 0.99) forwards;
}
I saw another question that said the closest thing is :active but it requires the mouse to be held down. If I want it to be onclick, I need to use Javascript. But I don't know what I need to write to trigger the animation.
And is it also possible to make it so that when I pop 1 balloon, all the others will pop too automatically with a 1s delay inbetween? (There are 5 balloons).
You can add and remove the class of the animation with JS using classList.
Add:
object.classList.add('balloon');
Remove:
object.classList.remove('balloon');
Working example:
const add = () => {
document.getElementById('balloon').classList.add('animation')
}
const remove = () => {
document.getElementById('balloon').classList.remove('animation')
}
#keyframes pop {
from {
opacity: 1;
transform: translateZ(0) scale(1, 1);
}
to {
opacity: 0;
transform: translateZ(0) scale(1.5, 1.5);
}
}
.animation {
animation: pop 0.5s cubic-bezier(0.16, 0.87, 0.48, 0.99) forwards;
}
.balloon {
height: 125px;
width: 110px;
background-color: #FF6B6B;
border-radius: 50%;
}
.controls{
position: absolute;
bottom: 10px;
right: 10px;
}
<div id="balloon" class="balloon" onmouseover="add()"></div>
<div class="controls">
<button onClick="add()">Hide</button>
<button onClick="remove()">Show</button>
</div>
Here is a solution which makes balloons hiding one by one with interval .5s between them
var balloons = document.getElementsByClassName('balloon');
[...balloons].forEach( (e, i)=>{
e.onmouseover = function() {
this.classList.add('hidden');
setTimeout(hideAll, 500, balloons);
}
});
function hideAll(arg){
[...arg].forEach( (e, i)=>{
if ( ! e.classList.contains('hidden') ) {
e.style.animationDelay = i+'s';
e.classList.add('hidden');
}
});
}
#keyframes pop
{
from{
opacity:1;
transform: translateZ(0) scale(1,1);
}
to{
opacity:0;
transform: translateZ(0) scale(1.5,1.5);
}
}
.balloon.hidden
{
animation: pop .5s cubic-bezier(0.16, 0.87, 0.48, 0.99) forwards;
}
<div class="balloon">Balloon</div>
<div class="balloon">Balloon</div>
<div class="balloon">Balloon</div>
<div class="balloon">Balloon</div>
<div class="balloon">Balloon</div>
I need to add page preloader when the user clicks on the login button in my project.so I create a sample page by including a submit button. and created a spinner as a preloader by using CSS as well as a javascript function to execute the spinner & fade it out and load another page call welcome.html
<!DOCTYPE html>
<html>
<head>
<link rel="stylesheet" type="text/css" href="style.css">
</head>
<body>
<div class="overlay"> <div class="spinner"></div>
</div>
<input type="submit" name="click me" id="submit">
**here is the javascript function**
<script>
(function(){
var spinner =document.getElementById("spinner");
var loading = 0;
var id = setInterval(frame,20);
function frame(){
if(loading==100){
clearInterval(id);
window.open("welcome.html","_self");
} else {
loading = loading + 1;
if(loading==90){
spinner.style.animation ="fadeout 1s ease";
}
}
}
})();
</script>
</body>
</html>
**here is the style sheet for preloader**
.overlay{
position: fixed;
top: 0;
left: 0;
right: 0;
bottom: 0;
background-color: #ff6347;
z-index: -999;
}
.spinner {
position: fixed;
top: 33%;
left: 48%;
width: 60px;
height: 60px;
background-color: black;
-webkit-animation: sk-rotateplane 1.2s infinite ease-in-out;
animation: sk-rotateplane 1.2s infinite ease-in-out;
}
**here is the keyframe code for fadeout**
#keyframes fadeout {
from {opacity: 1;}
to{opacity: 0;}
}
}
#-webkit-keyframes sk-rotateplane {
0% { -webkit-transform: perspective(120px) }
50% { -webkit-transform: perspective(120px) rotateY(180deg) }
100% { -webkit-transform: perspective(120px) rotateY(180deg) rotateX(180deg) }
}
#keyframes sk-rotateplane {
0% {
transform: perspective(120px) rotateX(0deg) rotateY(0deg);
-webkit-transform: perspective(120px) rotateX(0deg) rotateY(0deg)
} 50% {
transform: perspective(120px) rotateX(-180.1deg) rotateY(0deg);
-webkit-transform: perspective(120px) rotateX(-180.1deg) rotateY(0deg)
} 100% {
transform: perspective(120px) rotateX(-180deg) rotateY(-179.9deg);
-webkit-transform: perspective(120px) rotateX(-180deg) rotateY(-179.9deg);
}
}
what I needed was, the user clicks on the button and then shows the preloader. But the thing is when I run the page button appears at the same time spinner preloader is running without clicking on the button and after the loading welcome.html page opens.
You should hide the spinner initially and only show it when the loading starts. So you could change the frame function to something like this:
function loading(){
if(loading==0) {
spinner.classList.add('active');
} else if(loading==100){
clearInterval(id);
window.open("welcome.html","_self");
spinner.classList.remove('active');
} else {
loading = loading + 1;
if(loading==90){
spinner.style.animation ="fadeout 1s ease";
}
}
}
Also you could add some sort of click listener to the submit button rather than setting an interval to check every 20 milliseconds on page load already, that seems unnecessary.
And then change this in your css:
.spinner {
display: none;
position: fixed;
top: 33%;
left: 48%;
width: 60px;
height: 60px;
background-color: black;
-webkit-animation: sk-rotateplane 1.2s infinite ease-in-out;
animation: sk-rotateplane 1.2s infinite ease-in-out;
}
.spinner.active {
display: block
}
First add
.overlay{
display:none;
}
in css and then on click function of submit button add
document.getElementById("overlayId").style.display = "block";
If you are using javascript
and
$(".overlay").css("display", "block");
if you are using jquery
N.B.: overlayId is the Id of overlay DIV
Take a look at this simple JsFiddle I created.
What it does is simply inserts a new li element with a slide effect from left, when the ul display is on flex and inline-block.
Something similar to that is Stackoverflow chat avatars when someone joins.
#-webkit-keyframes enter {
0% { /*opacity:0;*/ -webkit-transform: translateX(-100%); }
100% { /*opacity:1;*/ -webkit-transform: translateX(0px); }
}
#-webkit-keyframes moves {
0% { /*opacity:0;*/ -webkit-transform: translateX(-50px); }
100% { /*opacity:1;*/ -webkit-transform: translateX(0px); }
}
in my enter animation, I start with translate -100% because I want my item come from left distanced by his size.
and in the moves animation, I want to move the whole ul to the right, by the size of the entering element.
Now I set it hard-coded, to 50px because my elements are set to 50px:
li {
width: 50px;
height: 50px;
display: inline-block;
background-color: red;
}
How can I make it calculate the width OR height automatically, on how much to translate the ul?
Example: Calculate these 50px automatically
You can do this by animating only the added element by using negative margin:
setTimeout(() => {
var item = $("<li></li>").addClass("enter");
$("ul").prepend(item).addClass('move');
}, 2000);
ul {
display: flex;
transition-timing-function: ease-out;
transition: all .2s;
}
li {
--h:50px;
width: 50px;
height: var(--h);
display: inline-block;
background-color: red;
}
.enter {
animation: enter 1s;
}
#keyframes enter {
0% {
transform: translateX(-100%);
margin-left: calc(var(--h) * -1);
}
100% {
transform: translateX(0px);
margin-left: 0
}
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<ul>
<li class="my-flex-thing">a</li>
<li class="my-flex-thing">b</li>
</ul>
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>