I have created the following on CodePen
HTML
<div class="demo-container clocks active bounce">
<section class="seconds-container">
<section class="seconds"></section>
</section>
</article>
</div>
CSS
body {
margin: 0;
}
.demo-container.clocks {
background: #3cd19e;
padding: 0;
width: 500px;
height: 548px;
margin: 0;
overflow: hidden;
}
.hours-container {
animation: rotate 43200s infinite linear;
}
.linear {
.minutes-container {
animation: rotate 3600s infinite linear;
}
.seconds-container {
animation: rotate 60s infinite linear;
}
}
.steps {
.minutes-container {
animation: rotate 3600s infinite steps(60);
}
.seconds-container {
animation: rotate 60s infinite steps(60);
}
}
.local.steps {
.minutes-container {
animation: none;
}
}
.bounce {
.minutes-container {
transition: transform 0.3s cubic-bezier(.4,2.08,.55,.44);
}
.seconds-container {
transition: transform 0.2s cubic-bezier(.4,2.08,.55,.44);
}
}
.seconds {
background: url(https://svgur.com/i/Hmu.svg);
width: 500px;
height: 548px;
position: absolute;
left: 0;
top: 0;
transform-origin: 50%;
z-index: 8;
animation: rotate 60s infinite steps(60);
}
#keyframes rotate {
100% {
/*transform: rotateZ(360deg);*/
}
}
.seconds-container {
transition: transform 0.2s cubic-bezier(.4,2.08,.55,.44);
}
JS
/*
* Main function to set the clock times
*/
(function() {
// Start the seconds container moving
moveSecondHands();
})();
/*
* Move the second containers
*/
function moveSecondHands() {
var containers = document.querySelectorAll('.bounce .seconds-container');
setInterval(function() {
for (var i = 0; i < containers.length; i++) {
if (containers[i].angle === undefined) {
containers[i].angle = 6;
} else {
containers[i].angle += 6;
}
containers[i].style.webkitTransform = 'rotateZ('+ containers[i].angle +'deg)';
containers[i].style.transform = 'rotateZ('+ containers[i].angle +'deg)';
}
}, 1000);
for (var i = 0; i < containers.length; i++) {
// Add in a little delay to make them feel more natural
var randomOffset = Math.floor(Math.random() * (100 - 10 + 1)) + 10;
containers[i].style.transitionDelay = '0.0'+ randomOffset +'s';
}
}
I basically want the image to rotate 360 and have that bounce effect as well. Just can't figure out how to keep the image in the same position so the rotation occurs from the central point (the image stays in the same location)
Any ideas?
So basically I need to combine animation: rotate 60s infinite steps(60); with the bounce effect shown in the codepen.
.seconds {
background: url(https://svgur.com/i/Hmu.svg);
width: 1000px;
height: 1097px;
position: relative;
left: 0;
top: 0;
transform-origin: 50%;
z-index: 8;
animation: rotate 2s infinite;
}
#keyframes rotate {
from {
transform: scale(1);
}
75% {
transform: scale(0.98);
}
50% {
transform: scale(0.95);
}
25% {
transform: scale(0.98);
}`enter code here`
to {
transform: scale(1);
}
}
Related
I have a simple beating animation and I want to check when one iteration ends or reaches 50% keyframe or something like that, is this possible?
For now this is what I have tried but this doesn't track anything:
function prepareLabelBeatStart() {
const prepareLabelGroup = document.getElementById("prepare-label-group");
prepareLabelGroup.classList.add("beaton");
prepareLabelGroup.addEventListener("webkitAnimationEnd", beatonEnd);
function beatonEnd(e) {
console.log('FUCK');
if (e.animationName === 'beaton') {
console.log('one iteration has been end'); // this is not working
prepareLabelGroup.removeEventListener("webkitAnimationEnd", beatonEnd);
}
}
}
setTimeout(() => prepareLabelBeatStart(), 2500);
.beaton {
animation: beaton 1.5s ease-in-out infinite both;
}
#keyframes beaton {
0% { transform: scale(1) }
50% { transform: scale(0.5) }
100% { transform: scale(1) }
}
#prepare-label-group {
position: absolute;
background: black;
width: 50px;
}
<div id="prepare-label-group">ff</div>
May be this will help.
function prepareLabelBeatStart() {
const prepareLabelGroup = document.getElementById("prepare-label-group");
let percent = document.getElementById("percent");
prepareLabelGroup.classList.add("beaton");
percent.textContent = 0+"%"
let total = 6; //6 seconds
let step = 1;
let Track = setInterval(function(){
percent.textContent = Math.round(((step++) / total) * 100) + "%";
}, 1000);
let Track2 = setInterval(function(){
if (prepareLabelGroup.classList.contains("beaton")) {
prepareLabelGroup.classList.remove("beaton");
}
clearInterval(Track);
clearInterval(Track2);
}, 6000);
}
prepareLabelBeatStart();
setInterval(function(){
prepareLabelBeatStart();
}, 6500);
.beaton {
animation: beaton 1.5s ease-in-out infinite both;
}
#keyframes beaton {
0% { transform: scale(1) }
50% { transform: scale(0.5) }
100% { transform: scale(1) }
}
#prepare-label-group {
position: absolute;
background: black;
width: 50px;
text-align:center;
}
#percent{
color:white;
}
<div id="prepare-label-group"><div id="percent">0%</div></div>
Hi: I am trying to make something using javascript's createElement. I am trying to create something like this:
Currently what I have is working, however it goes from the top down instead of bottom up. My code is this:
function recal(color, user, content) {
var element = document.createElement("p")
element.className = "flyin"
var spanelement = document.createElement("span")
spanelement.appendChild(document.createTextNode(user + ': '))
element.appendChild(spanelement)
element.innerHTML = '<span style = "color:' + color+ ';font-weight:bold">' + user + ': </span>' + content
var x = document.getElementById('messagecontainer')
x.appendChild(element)
setTimeout(function () {
element.classList.add('fade-out');
element.onanimationend = (e) => {
if (e.srcElement.classList.contains('fade-out')) {
element.parentNode.removeChild(element);
}
}
}, 10000)
;
}
.fadeout {
opacity: 1;
-webkit-transition: opacity 1000ms linear;
transition: opacity 1000ms linear;
}
body {
font-family: Arial;
font-weight: bold;
margin: 0px
}
#messagecontainer{
/*probably something here*/
}
.flyin {
-webkit-animation: test1 .2s linear;
}
#-webkit-keyframes test1 {
0% {
-webkit-transform: translateX(75%);
}
100% {
-webkit-transform: translateX(0%);
}
}
.fade-out {
animation: fade 2s;
-webkit-animation: fade .5s;
-moz-animation: fade .5s;
}
#keyframes fade {
from {
opacity: 1
}
to {
opacity: 0
}
}
#-moz-keyframes fade {
from {
opacity: 1
}
to {
opacity: 0
}
}
#-webkit-keyframes fade {
from {
opacity: 1
}
to {
opacity: 0
}
}
<button onclick='recal("blue","Komali","hello!")'>click me!</button>
<div id="messagecontainer"></div>
How can I have it so it goes from the bottom instead of the top? Any help is appreciated
You were on track, you just need to add position: absolute; to #messagecontainer and position it left bottom, like this:
#messagecontainer {
position: absolute;
left: 0;
bottom: 0;
}
function recal(color, user, content) {
var element = document.createElement("p")
element.className = "flyin"
var spanelement = document.createElement("span")
spanelement.appendChild(document.createTextNode(user + ': '))
element.appendChild(spanelement)
element.innerHTML = '<span style = "color:' + color + ';font-weight:bold">' + user + ': </span>' + content
var x = document.getElementById('messagecontainer')
x.appendChild(element)
setTimeout(function() {
element.classList.add('fade-out');
element.onanimationend = (e) => {
if (e.srcElement.classList.contains('fade-out')) {
element.parentNode.removeChild(element);
}
}
}, 10000);
}
.fadeout {
opacity: 1;
-webkit-transition: opacity 1000ms linear;
transition: opacity 1000ms linear;
}
body {
font-family: Arial;
font-weight: bold;
margin: 0;
}
#messagecontainer {
position: absolute;
left: 0;
bottom: 0;
}
.flyin {
-webkit-animation: test1 .2s linear;
}
#-webkit-keyframes test1 {
0% {
-webkit-transform: translateX(75%);
}
100% {
-webkit-transform: translateX(0%);
}
}
.fade-out {
animation: fade 2s;
-webkit-animation: fade .5s;
-moz-animation: fade .5s;
}
#keyframes fade {
from {
opacity: 1
}
to {
opacity: 0
}
}
#-moz-keyframes fade {
from {
opacity: 1
}
to {
opacity: 0
}
}
#-webkit-keyframes fade {
from {
opacity: 1
}
to {
opacity: 0
}
}
<button onclick='recal("blue","Komali","hello!")'>click me!</button>
<div id="messagecontainer"></div>
I am trying to count the numbers of clicks that click on the fox image.
But it does not works.
I am sure that this onclick function is works.
$(document).ready(function () {
var i = 0;
$(".fox").click(function(){
$(".animal-quantity").html(i++);
});
});
Can anyone help me with this issue.
Thank you very much.
Link below is my full code.
https://jsfiddle.net/rbtj3ywo/1/
In your CSS code exists
#animals {
pointer-events: none;
}
Note: pointer-events: none Means Disables any action.
Just delete it to solve the problem.
Your pointer-events: none; is not correct.
$(document).ready(function () {
var i = 0;
$(".fox").on('click',function(){
console.log("hi");
$("#quantity > span").text(i++);
});
});
(function() {
var NUMBER_OF_ANIMALS = 10;
function init() {
/* Get a reference to the element that will contain the animals */
var container = document.getElementById('animals');
/* Fill the empty container with new animals */
try {
for (var i = 0; i < NUMBER_OF_ANIMALS; i++) {
container.appendChild(createAnimal());
}
}
catch(e) {
}
}
function randomInteger(low, high) {
return low + Math.floor(Math.random() * (high - low));
}
function randomFloat(low, high) {
return low + Math.random() * (high - low);
}
function pixelValue(value) {
return value + 'px';
}
function durationValue(value) {
return value + 's';
}
/*
Uses an img element to create each animal.
*/
function createAnimal() {
/* Start by creating a wrapper div, and an empty img element */
var animalDiv = document.createElement('div');
var image = document.createElement('img');
/* Randomly choose a animal image and assign it to the newly created element */
image.src ='https://pngimage.net/wp-content/uploads/2018/05/cute-animals-png-4.png';
image.style.width = randomInteger(7, 20) + 'vw';
image.className = 'fox';
/* Position the animal at a random location along the screen */
animalDiv.style.top = pixelValue(randomInteger(-100, -250));
animalDiv.style.left = randomInteger(0, 60) + 'vw';
/* Set the -webkit-animation-name property with these values */
animalDiv.style.webkitAnimationName ='fade, drop';
animalDiv.style.animationName ='fade, drop';
var fadeAndDropDuration = durationValue(randomFloat(1.2, 8.2));
animalDiv.style.webkitAnimationDuration = fadeAndDropDuration + ', ' + fadeAndDropDuration;
animalDiv.style.animationDuration = fadeAndDropDuration + ', ' + fadeAndDropDuration;
var animalDelay = durationValue(randomFloat(0, 1));
animalDiv.style.webkitAnimationDelay = animalDelay + ', ' + animalDelay;
animalDiv.style.animationDelay = animalDelay + ', ' + animalDelay;
animalDiv.appendChild(image);
return animalDiv;
}
init();
}
)();
.fox {
z-index: 100;
}
#animals {
position: fixed;
top: 0;
left: 0;
right: 0;
width: 100%;
z-index: 98;
}
#animals > div {
position: relative;
-webkit-animation-iteration-count: infinite;
-webkit-animation-direction: normal, normal;
-webkit-animation-timing-function: linear, ease-in;
-webkit-backface-visibility: hidden;
animation-iteration-count: infinite;
animation-direction: normal, normal;
animation-timing-function: linear, ease-in;
backface-visibility: hidden;
}
#animals > div > img {
-webkit-animation-iteration-count: infinite;
-webkit-animation-direction: alternate;
-webkit-animation-timing-function: linear;
-webkit-backface-visibility: hidden;
animation-iteration-count: infinite;
animation-direction: alternate;
animation-timing-function: linear;
}
#-webkit-keyframes fade {
0%, 90% {
opacity: 1;
}
100% {
opacity: 0;
}
}
#keyframes fade {
0%, 90% {
opacity: 1;
}
100% {
opacity: 0;
}
}
#-webkit-keyframes drop {
0% {
-webkit-transform: translate3d(0, 0, 0);
}
100% {
-webkit-transform: translate3d(0, 1100px, 0);
}
}
#keyframes drop {
0% {
transform: translate3d(0, 0, 0);
}
100% {
transform: translate3d(0, 1100px, 0);
}
}
.quantity{
position: absolute;
left: 0;
right: 0;
text-align: center;
top: 100px;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div id="animals"></div>
<img src="https://img.rawpixel.com/s3fs-private/rawpixel_images/website_content/pf-misctexture01-beer-000_5.jpg?w=800&dpr=1&fit=default&crop=default&q=65&vib=3&con=3&usm=15&bg=F4F4F3&ixlib=js-2.2.1&s=c1552a7bdc2ea7b6e17d8d0d893c15be" class="background" style="width: 100%; position: relative;">
<div class="quantity" id="quantity">Total quantity: <span class="animal-quantity">0</span></div>
In this question there is an accepted answer How to create an animation with rarity of it to appear together with animations that always appear?
It contains this
https://jsfiddle.net/d25kx6cj/5/
<div id="boxes">
<div id="box1" class="box"></div>
<div id="box2" class="box"></div>
<div id="box4" class="box"></div>
<div id="box3" class="box"></div>
</div>
But it looks that it's too complicated. Is there another way.
The thing is that it can become more complicated.
I'm trying to achieve this in an easier way:
var box1 = document.getElementById("box1"); /* The one with the rarity */
var box2 = document.getElementById("box2");
var box3 = document.getElementById("box3"); /* Maybe give it a chance of which color */
var boxes = document.getElementById("boxes");
var box3Colors = {"blue": 90, "red": 50};
var btn = document.getElementById("btn");
btn.addEventListener("click", toggleAnimation);
boxes.classList.add("deactivated");
function randomizerWithChances(input) {
var array = [];
for(var item in input) {
if ( input.hasOwnProperty(item) ) {
for( var i=0; i<input[item]; i++ ) {
array.push(item);
}
}
}
/*console.log(array)
var randomizerValue = Math.floor(Math.random() * array.length);
console.log(randomizerValue)*/
return array[Math.floor(Math.random() * array.length)];
}
function propertyFromStylesheet(selector, attribute) {
var value;
[].some.call(document.styleSheets, function (sheet) {
return [].some.call(sheet.rules, function (rule) {
if (selector === rule.selectorText) {
return [].some.call(rule.style, function (style) {
if (attribute === style) {
value = rule.style.getPropertyValue(attribute);
return true;
}
return false;
});
}
return false;
});
});
return value;
}
var box1_defaultDurs = propertyFromStylesheet("#box1", "animation-duration");
var box2_defaultDur = parseFloat(propertyFromStylesheet("#box2", "animation-duration"));
var box4_defaultDur = parseFloat(propertyFromStylesheet("#box4", "animation-duration"));
var box3_defaultDurs = propertyFromStylesheet("#box3", "animation-duration");
var box1AppearChance = {no:6, yes:4} /* 40% Appear chance I guess*/
var box4AppearChance = {no:8, yes:2}
/*
defaultDurs.split(",").map(function(item) {
return item.trim();
});*/
var box1_defaultDur = box1_defaultDurs.split(",").map(function(item) {
return item.trim();
});
var box3_defaultDur = box3_defaultDurs.split(",").map(function(item) {
return item.trim();
});
var box1_defaultDurStart = parseFloat(box1_defaultDur[0]);
var box1_defaultDurEnd = parseFloat(box1_defaultDur[1]);
var box3_defaultDurStart = parseFloat(box3_defaultDur[0]);
var box3_defaultDurEnd = parseFloat(box3_defaultDur[1]);
var box3_delays = [];
function animationHandler() {
box3.style.backgroundColor = randomizerWithChances(box3Colors);
var box1Value = randomizerWithChances(box1AppearChance);
var box4Value = randomizerWithChances(box4AppearChance);
/*console.log(box1Value)*/
box3_delays[0] = "0s"; /* Put first delay value */
if (box1Value == "yes") {
box1.classList.add("active");
box2.style.animationDelay = box1_defaultDurStart + "s";
box3_delays[0] = box1_defaultDurStart + "s";
}
if (box1Value == "yes" || box4Value == "yes") {
box3_delays[0] = parseFloat(box3_delays[0]) + box2_defaultDur + "s";
}
/*box3.style.animationDelay = box3_defaultDurs.split(",").map(function(item) {
var itemTrimmed = item.trim();
return parseFloat(itemTrimmed) + box1_defaultDurStart + box2_defaultDur + "s";
});
}*/
/* Use this incase you have to summarize something with two delays, if it has 0s you might want to do something else or check if it's the first one in the array just to leave it alone. But in this case I didn't needed it */
/* box4.style.animationDelay = "0s"; To prevent NaN
Don't do this it it just breaks it just check it
*/
if (box4Value == "yes") {
box4.classList.add("active");
if ( isNaN(parseFloat(box2.style.animationDelay)) ) {
box4.style.animationDelay = box2_defaultDur + "s";
}
else if ( !isNaN(parseFloat(box2.style.animationDelay)) ) {
box4.style.animationDelay = parseFloat(box2.style.animationDelay) + box2_defaultDur + "s";
} /* box4 doesn't have a delay and we set one */
box3_delays[0] = parseFloat(box3_delays[0]) + box4_defaultDur + "s";
/* Delay of box3 is getting extended because of box4 when it appears */
}
if (box1Value == "yes" || box4Value == "yes") {
box3.style.animationDelay = [ parseFloat(box3_delays[0]) + "s", parseFloat(box3_delays[0]) + parseFloat(box3_defaultDurStart) + "s" ];
}
if (box1Value == "yes") {
if (box4Value == "no") {
box1.style.animationDelay = ["0s", box2_defaultDur + box3_defaultDurStart + box1_defaultDurStart + box3_defaultDurEnd + "s"]
}
else {
box1.style.animationDelay = ["0s", box2_defaultDur + box3_defaultDurStart + parseFloat(box4.style.animationDelay) + box1_defaultDurStart + box3_defaultDurEnd + "s"];
}
/* The + 2 is because of the box1_defaultDurStart which is needed */
/* And box3_defaultDurEnd also needed in this case */
}
}
function animationHandlerReset() {
box1.classList.remove("active");
box4.classList.remove("active"); /* And don't forget to remove the class at the end*/
/* Reset to default to stylesheet */
box1.style.removeProperty("animation-delay");
box2.style.removeProperty("animation-delay");
box3.removeAttribute("style"); /* or you could do this if you didn't give it any inline style by default */
box4.style.removeProperty("animation-delay");
}
function toggleAnimation() {
if (!boxes.classList.contains("deactivated")) {
animationHandlerReset();
boxes.classList.add("deactivated");
btn.innerHTML = "Start Animation";
}
else if (boxes.classList.contains("deactivated")) {
animationHandler();
boxes.classList.remove("deactivated");
btn.innerHTML = "Stop Animation"
}
}
#boxes {
}
.active {
display: inline-block!important;
}
.deactivated {
display: none!important;
/*visibility: hidden!important;*/
}
.box {
display: inline-block;
position: relative;
height: 50px;
width: 50px;
margin-left: 20px;
}
#box1 {background: #00afe8;}
#box2 {background: green;}
#box3 {background: blue;}
#box4 {background: orange;}
#keyframes box1-up {
0% { top: 70px;}
100% {top: 0px;}
}
#keyframes box1-down {
0% { top: 0px;}
100% {top: 70px; opacity: 0;}
}
#keyframes box4-anim {
0% { height: 50px; width: 50px; transform: scale(0.5) rotate(0deg); }
100% { height: 50px; width: 50px; transform: scale(1) rotate(180deg); }
}
#keyframes blend {
0% { opacity: 0; }
100% { opacity: 1; }
}
#box1 {
top: 70px;
display: none;
animation: box1-up 2s, box1-down 3s;
animation-fill-mode: forwards;
}
#box2 {
opacity: 0;
animation: blend 3s;
animation-fill-mode: forwards;
/*animation-delay: 3s;*/
}
#box3 {
opacity: 0;
animation: blend 3s, blend 4s reverse;
animation-fill-mode: forwards;
animation-delay: 3s, 6s; /* Both delays start together. Probably you want the other delay to be the twice as the size of the first one in this case for the end, but maybe not everytime */
}
#box4 {
display: none;
height: 0px;
width: 0px;
animation: box4-anim 1s;
animation-fill-mode: forwards;
}
<div id="boxes">
<div id="box1" class="box"></div>
<div id="box2" class="box"></div>
<div id="box4" class="box"></div>
<div id="box3" class="box"></div>
</div>
<button id="btn" style="margin-top: 200px;">Start Animation</button>
A simplified version of this?
Basically it is animations but it has a random chance that one of them appears. So box1 has a random chance that it appears and box4 which is the orange one, just has been called like that. Has a random chance to appear.
And box1 and box3 have a start and end animation. And that has all to be calculated and then used and I was wondering if there is an easier way to do it, because that's just so much and not sure.
I think jQuery but I don't know any good example to this.
I post you my solution trying to make whole animation very very easy to create and to understand.
As I said in my comments, my idea came from a question: "Ok, if some boxes sometimes there aren't, why should I always put them all on the stage? I put on stage only if I have to move it"
So, for my solution all the boxes are create on fly with jquery, looping a javascript object that I call "boxes":
var boxes={
"box1":{
percentual: 40, // 40% to appear on stage
animation: "box-up-down", // animation name
backgroundColor: "green" // background color
},
"box2":{
percentual: 100,
animation: "fade-in",
backgroundColor: "orange"
},
"box3":{
percentual: 100,
animation: "fade-in",
backgroundColor: "blue"
},
"box4":{
percentual: 20,
animation: "fade-in-out",
backgroundColor: "pink"
},
"box5":{
percentual: 100,
animation: "rotate-in-out",
backgroundColor: "red"
}
}
In this object you can put how many box you want (in my example they are 5). The first value is the probability of appearance on the stage (40% the first, 100% the second...). The second one define the name of animations that I wrote in CSS:
/*ANIMATIONS*/
.fade-in {
animation: fade-in 1s ease forwards;
}
.fade-in-out {
animation: fade-in-out 7s ease forwards;
}
.box-up-down {
animation: box-up-down 7s ease forwards;
}
.rotate-in-out {
animation: rotate-in-out 7s ease forwards;
}
#keyframes fade-in {
0% {
opacity: 0;
}
100% {
opacity: 1;
}
}
#keyframes fade-in-out {
0% {
opacity: 0;
}
14% {
opacity: 1;
}
86% {
opacity: 1;
}
100% {
opacity: 0;
}
}
#keyframes box-up-down {
0% {
top: 70px;
opacity: 0;
}
14% {
top: 0;
opacity: 1;
}
86% {
top: 0;
opacity: 1;
}
100% {
top: 70px;
opacity: 0;
}
}
#keyframes rotate-in-out {
0% {
transform: scale(0.5) rotate(0deg);
opacity: 0;
}
14% {
transform: scale(1) rotate(180deg);
opacity: 1;
}
86% {
transform: scale(1) rotate(180deg);
opacity: 1;
}
100% {
transform: scale(0.5) rotate(0deg);
opacity: 0;
}
}
It is important to understand that the pause is set in the animation itself. In my example I used 7seconds of animation: 1 for appear, 5 of pause period and 1 for disappear. See this for more information about the technique: Fade out, pause, then fade in an element - CSS Only. You have to use a proportion to find the exact percentual (in my example it was 14% and 86%).
Last arg is only the background color of the box.
To calculate the probability of appearance on the stage, I used a simple comparison between a random number and my percentage set in the javascript object:
let random=Math.floor(Math.random() * 100) + 1; //random number from 1 to 100
if(value.percentual>=random){
//create my box
}
This is all the script in action:
var boxes = {
"box1": {
percentual: 40, // 40% to appear on stage
animation: "box-up-down", // animation name
backgroundColor: "green" // background color
},
"box2": {
percentual: 100,
animation: "fade-in",
backgroundColor: "orange"
},
"box3": {
percentual: 100,
animation: "fade-in",
backgroundColor: "blue"
},
"box4": {
percentual: 20,
animation: "fade-in-out",
backgroundColor: "pink"
},
"box5": {
percentual: 100,
animation: "rotate-in-out",
backgroundColor: "red"
}
}
$("#btn").on("click", function(e) {
// set the init situation if I double click during the animations
let i = 0;
$("#boxes").html("");
// Create every block
$.each(boxes, function(index, value) {
let random = Math.floor(Math.random() * 100) + 1; //random number from 1 to 100
if (value.percentual >= random) {
let myBox = `<div id="${index}"
class="box ${value.animation}"
style="background-color:${value.backgroundColor};
animation-delay:${i}s;"
></div>`;
$(myBox).appendTo("#boxes");
i++;
}
});
});
.box {
display: inline-block;
position: relative;
transition: all 1s;
height: 50px;
width: 50px;
opacity:0;
background-color:#f2f2f2;
margin-right: 20px;
}
/*ANIMATIONS*/
.fade-in {
animation: fade-in 1s ease forwards;
}
.fade-in-out {
animation: fade-in-out 7s ease forwards;
}
.box-up-down {
animation: box-up-down 7s ease forwards;
}
.rotate-in-out {
animation: rotate-in-out 7s ease forwards;
}
#keyframes fade-in {
0% {
opacity: 0;
}
100% {
opacity: 1;
}
}
#keyframes fade-in-out {
0% {
opacity: 0;
}
14% {
opacity: 1;
}
86% {
opacity: 1;
}
100% {
opacity: 0;
}
}
#keyframes box-up-down {
0% {
top: 70px;
opacity: 0;
}
14% {
top: 0;
opacity: 1;
}
86% {
top: 0;
opacity: 1;
}
100% {
top: 70px;
opacity: 0;
}
}
#keyframes rotate-in-out {
0% {
transform: scale(0.5) rotate(0deg);
opacity: 0;
}
14% {
transform: scale(1) rotate(180deg);
opacity: 1;
}
86% {
transform: scale(1) rotate(180deg);
opacity: 1;
}
100% {
transform: scale(0.5) rotate(0deg);
opacity: 0;
}
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div id="boxes"></div>
<button id="btn" style="margin-top: 200px;">Start Animation</button>
I have an element which is randomly animated with CSS and JS with the help of CSS custom properties in the following way:
var myElement = document.querySelector('#my-element');
function setProperty(number) {
myElement.style.setProperty('--animation-name', 'vibrate-' + number);
}
function changeAnimation() {
var number = Math.floor(Math.random() * 3) + 1;
setProperty(number);
/* restart the animation */
var clone = myElement.cloneNode(true);
myElement.parentNode.replaceChild(clone, myElement);
}
myElement.addEventListener('animationend', changeAnimation, false);
#my-element {
width: 50px;
height: 50px;
background: #333;
}
:root {
--animation-name: vibrate-1;
}
#my-element {
animation: 3.3s 1 alternate var(--animation-name);
}
#keyframes vibrate-1 {
0% {
opacity: 0;
transform: scale(0.95);
}
50% {
opacity: 1;
transform: scale(1);
}
100% {
opacity: 0;
transform: scale(0.9);
}
}
#keyframes vibrate-2 {
0% {
opacity: 0;
transform: scale(0.5);
}
50% {
opacity: 1;
transform: scale(0.9);
}
100% {
opacity: 0;
transform: scale(0.5);
}
}
#keyframes vibrate-3 {
0% {
opacity: 0;
transform: scale(0.3);
}
50% {
opacity: 1;
transform: scale(1);
}
100% {
opacity: 0;
transform: scale(0.8);
}
}
<div id="my-element"></div>
The idea behind is to have a set of animations which switch on each animation’s end randomly to another one. (that for the opacity in the end is always 0 to make a smooth invisible switch.)
Now, surprisingly, this code above runs just fine, except that it does only once and then stop.
I now there are JS loop techniques but I have no idea how to exactly implement them inside this workflow.
Can someone help me?
When you replace the element with the cloned element, you should reassign the animationend event listener:
var clone = myElement.cloneNode(true);
clone.addEventListener('animationend', changeAnimation, false);
myElement.parentNode.replaceChild(clone, myElement);
By the way, variables in JavaScript can't contain -, so my-element should be myElement.
Another simple idea is to rely on animationiteration and make the animation to run infinite then you no more need to clone the element. You simply change the animation name each iteration and you will have the needed effect:
var myElement = document.querySelector('#my-element');
function setProperty(number) {
myElement.style.setProperty('--animation-name', 'vibrate-' + number);
}
function changeAnimation() {
var number = Math.floor(Math.random() * 3) + 1;
setProperty(number);
}
myElement.addEventListener('animationiteration', changeAnimation, false);
#my-element {
width: 50px;
height: 50px;
background: #333;
}
#my-element {
animation: 3.3s alternate infinite var(--animation-name,vibrate-1);
}
#keyframes vibrate-1 {
0% {
opacity: 0;
transform: scale(0.95);
}
50% {
opacity: 1;
transform: scale(1);
background:green;
}
100% {
opacity: 0;
transform: scale(0.9);
}
}
#keyframes vibrate-2 {
0% {
opacity: 0;
transform: scale(0.5);
}
50% {
opacity: 1;
transform: scale(0.9);
background:red;
}
100% {
opacity: 0;
transform: scale(0.5);
}
}
#keyframes vibrate-3 {
0% {
opacity: 0;
transform: scale(0.3);
}
50% {
opacity: 1;
transform: scale(1);
background:blue;
}
100% {
opacity: 0;
transform: scale(0.8);
}
}
<div id="my-element"></div>
Another way is to simply keep one animation and adjust the scale values (or any other values) and you will have a better random behavior.
var myElement = document.querySelector('#my-element');
function changeAnimation() {
var n1 = Math.random();
myElement.style.setProperty('--s1',n1);
var n2 = Math.random();
myElement.style.setProperty('--s2',n2);
var c1 = Math.floor(Math.random()*255);
myElement.style.setProperty('--c1',c1);
var c2 = Math.floor(Math.random()*255);
myElement.style.setProperty('--c2',c2);
}
myElement.addEventListener('animationiteration', changeAnimation, false);
#my-element {
width: 50px;
height: 50px;
background: #333;
}
#my-element {
animation: 3.3s alternate infinite vibrate;
}
#keyframes vibrate {
0% {
opacity: 0;
transform: scale(var(--s1,0.95));
}
50% {
opacity: 1;
transform: scale(1);
background:rgb(255,var(--c1,0),var(--c2,0));
}
100% {
opacity: 0;
transform: scale(var(--s2,0.9));
}
}
<div id="my-element"></div>