How can I restart a CSS animation with random values in a loop?

  • A+
Category:Languages

I have an element which is randomly animated with CSS and JS with the help of CSS custom properties in the following way:

HTML:

<div id="my-element"></div> 

CSS:

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

JS:

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

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 – as I am quite a newbie to JS;-) 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? Thanks in advance!

Stefan

 


Another simple idea is to rely on animationiteration and make the animation to run infinite and no need to clone the element. You simply change the animation each iteration and since the duration is always the same it will create 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>

Comment

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen: