Onclick event on moving images does not work - javascript

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>

Related

Track when CSS keyframe animation reaches 50%

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>

Add element to bottom of container and shift elements up

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>

Rotate / Bounce Image from the Central Axis

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);
}
}

How to create an animation with rarity of it to appear together with animations that always appear?

How to create an animation with rarity of it to appear together with animations that always appear?
Example here:
The number 1 has a rare chance to appear, let's say 40% chance. When it doesn't appear, it will start with 2 then after the animation of 2 is done 3 will start.
Should it 1 make it through the chance, it will appear and move up and after its animation is done, 2 will play and then after 2, 3 will play. So they just blend in as example.
2 and 3 will always appear, but 1 has a 40% for it to appear, as example. On 3 I've managed to put a random background chance on it. I've commented it on the code.
Should 1 not appear, then it should act like display: none. When I put display: none however on box1, the animation never starts, or it started but I can't see it, but I put it in the keyframes.
What I'm thinking is that, I guess it requires Javascript so it can change the animation-delay CSS property, I'm not sure though.
This is what I have so far: https://jsfiddle.net/edy3xjvz/2/
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}; /* Blue has 90% chance and red has 50% not sure if done right, but what if I want to add a "green" with the chance of 90% too like "blue"??? */
/* Probably has to be done here, or when reaching a certain area, maybe with a button */
/*document.onload*/
var btn = document.getElementById("btn");
btn.addEventListener("click", startAnimation);
boxes.style.display = "none";
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);
}
}
}
return array[Math.floor(Math.random() * array.length)];
}
/* Start Animation */
function startAnimation() {
boxes.style.display = "none"; /* to replay but doesn't work*/
/* Do radomize stuff */
/* Don't really know for box1 */
/* I've tried box3, like that before
var random2 = box3Colors[Math.floor(Math.random() * box3Colors.length)]
box3.style.backgroundColor = random2;*/
box3.style.backgroundColor = randomizerWithChances(box3Colors);
/* Animation starts here */
boxes.style.display = "block";
}
#boxes {
}
.box {
display: inline-block;
position: relative;
height: 50px;
width: 50px;
margin-left: 20px;
}
#box1 {background: #00afe8;}
#box2 {background: green;}
#box3 {background: blue;}
#keyframes box1-up {
0% { top: 70px; position: relative; visibility: visible;}
100% {top: 0px; position: relative; visibility: visible;}
}
#keyframes blend {
0% { opacity: 0; }
100% { opacity: 1; }
}
#box1 {
top: 70px;
/* display: none; Can't start with this I wanted that when it isn't there, it should not appear but with display: none it didn't work because it can never appear then */
/*position: absolute; visibility: hidden;*/ /* So had to use this but when using this
it didn't work the box is somehow upside
https://i.imgur.com/3vER5ja.png so not sure */
animation: box1-up 2s;
animation-fill-mode: forwards;
}
#box2 {
opacity: 0;
animation: blend 3s;
animation-fill-mode: forwards;
animation-delay: 3s;
}
#box3 {
opacity: 0;
animation: blend 3s;
animation-fill-mode: forwards;
animation-delay: 5s;
}
<div id="boxes">
<div id="box1" class="box"></div>
<div id="box2" class="box"></div>
<div id="box3" class="box"></div>
</div>
<button id="btn" style="margin-top: 200px;">Start Animation</button>
Below there should be a button. What I've tried is to put a randomizer for box3 background color, seemed to work. I've tried to use box1 but display: none broke it.
I've tried to make something that when the animation doesn't start at all, that box2 is like not here, but when I use display: none the animation never starts not sure why.
https://jsfiddle.net/edy3xjvz/3/
Then I removed it so this is what you seen on the snippet above. https://jsfiddle.net/edy3xjvz/4/
Here's a quick PoC of how it could behave with our without box1 if I'm understanding your description correctly so that if the active class is there it will look as you have it, and if not then give the illusion equivalent of display: none, hope it helps, cheers.
const box1 = document.getElementById('box1');
toggleActive = () => {
let classes = box1.classList;
classes.contains('active') ? classes.remove('active') : classes.add('active');
}
.container {
display: inline-block;
outline: lightgray 1px dashed;
padding: 1rem;
margin: 1rem;
}
.container div {
display: inline-block;
height: 5rem;
width: 5rem;
background-color: lime;
opacity: 0;
animation: reveal 3s ease forwards;
}
.container div:nth-child(2) {
animation-delay: 1s;
}
.container div:nth-child(3) {
animation-delay: 2s;
}
.container div:not(:last-child) {
margin-right: 1rem;
}
#box1 {
height: 0;
width: 0;
margin: 0;
transform: translateY(6rem);
transition: transform 1s ease;
}
#box1.active {
height: 5rem;
width: 5rem;
margin-right: 1rem;
animation: revealUp 2s ease forwards;
}
#keyframes reveal {
to { opacity: 1 }
}
#keyframes revealUp {
to {
opacity: 1;
transform: translateY(0);
}
}
<div class="container">
<div id="box1" class="active"></div>
<div id="box2"></div>
<div id="box3"></div>
</div>
<br/>
<button onclick="toggleActive()">Toggle First One</button>
I think the animation handling, as in how it should be randomized and then what happens with the other animations, has to be kinda done manually but you can save the values or get them.
But that what I made is basically a basic concept and you can do even more stuff, but you have to adjust the delays and all that stuff.
This is the first concept:
https://jsfiddle.net/8z9obyLh/
Also you have to notice that once display is gone that the delay will start from there depending on which element just got out of display none.
The other one has a bit complex way but just look at it and how it's done.
Tbh, there should be another way to do this, which I think there is.
https://jsfiddle.net/d25kx6cj/5/
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>

Is there a better way to do complex animations with start and end animations that are randomized?

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>

Categories