1

Yesterday I asked a question (original question) that was promptly answered, but even though a solution was found, I don't understand why this is working the way it is. I can duplicate this solution for other things I need to do but before I continue on I would like to understand why this works the way it does.

So basically I made three functions that called each other. The 1st called the second upon "animationend" and the second called the third upon an "animationend" and the finally the third function called the first to start the cycle all over again - BUT My original code though lacked;

document.getElementById("rightBoxTwo").style.animation = "none";

which was needed in-order for the third function to call the first so the cycle starts all over again. Without the above code in each function the three functions would work only once and then stop. The answer that StackOverFlow user; ScientiaEtVeritas gave me included a CodePen which had a working example of what I needed and a brief explanation

So, I think you have several options: What could work is that you reset the the animation of rightBox in function runTwo with animation: none. If you assign scrollTextTwo 10s back to the rightBox it should start again. Equivalent for the other ones.

So finally my question is WHY does the animation need to be cleared, and why does the .style.animation = "none"; accomplish this?

below is the working code after a solution was presented...

<body onload="runOne()">
function runOne() {
  var x = document.getElementById("rightBox");
  x.addEventListener("animationend",runTwo);
  document.getElementById("rightBox").style.animation = "scrollTextTwo 10s";
  document.getElementById("rightBoxTwo").style.animation = "none";
}
function runTwo() {
  var x = document.getElementById("rightBoxTwo");
  x.addEventListener("animationend",runThree);
  document.getElementById("rightBoxTwo").style.animation = 
    "scrollTextTwo 10s";
  document.getElementById("rightBoxThree").style.animation = "none";
}
function runThree() {
  var x = document.getElementById("rightBoxThree");
  x.addEventListener("animationend",runOne);
  document.getElementById("rightBoxThree").style.animation = 
    "scrollTextTwo 10s";
  document.getElementById("rightBox").style.animation = "none";
}
Community
  • 1
  • 1
Ghoyos
  • 604
  • 2
  • 7
  • 18
  • 5
    It's like turning on a light. It the switch is already in the on position; you need to switch it off before you can switch on again. – Malk Aug 05 '16 at 17:35
  • 3
    It's like filling a glass of water. If the glass is already full, you need to empty it before you can fill it up again. – blex Aug 05 '16 at 17:36

2 Answers2

5

The simplest reason is because setting the animation to the same thing twice (or more times) in a synchronous manner like a for loop is the same as doing it once:

let box = document.getElementById('box');

// animation happens once
for (let i = 0; i < 5; i++) {
  box.style.animation = 'fade .5s';
}
@keyframes fade {
  from {
    opacity: 1
  }
  to {
    opacity: 0
  }
}
#box {
  height: 200px;
  width: 200px;
  margin: 50px;
  background: #018bbc;
}
<div id="box"></div>

The behavior is the same even if you delay the animation so each time it runs after a possible render:

let box = document.getElementById('box');

// animation still happens once
for (let i = 0; i < 5; i++) {
  setTimeout(function() {
    box.style.animation = 'fade .5s';
  }, i * 1000);
}
@keyframes fade {
  from {
    opacity: 1
  }
  to {
    opacity: 0
  }
}
#box {
  height: 200px;
  width: 200px;
  margin: 50px;
  background: #018bbc;
}
<div id="box"></div>

But if I reset the animation before each step, the engine has to re-set the animation, which in a way means to "install the animation again", meaning it will be animated again:

let box = document.getElementById('box');

box.addEventListener('animationend', function() {
  box.style.animation = 'none';
});

// animation now happens every time
for (let i = 0; i < 5; i++) {
  setTimeout(function() {
    box.style.animation = 'fade .5s';
  }, i * 1000);
}
@keyframes fade {
  from {
    opacity: 1
  }
  to {
    opacity: 0
  }
}
#box {
  height: 200px;
  width: 200px;
  margin: 50px;
  background: #018bbc;
}
<div id="box"></div>
nem035
  • 34,790
  • 6
  • 87
  • 99
  • oh so what your saying is the function is "installing" the animation on to the page. but the amount of times its animated is up to me based on css or other code? so the way i did it isnt the proper way to run it multiple times? – Ghoyos Aug 05 '16 at 17:53
  • Well yes, you can control how many times something is animated with JS and also only with CSS, as [@Malk showed in his answer](http://stackoverflow.com/a/38795001/3928341). As far as what is the proper way, using CSS is most likely a better option since the browser can do the animation with no bugs (or at least much less) and faster than it would be if you wrote the code yourself. – nem035 Aug 05 '16 at 17:55
  • I thank you sir, and yes malk's answer is very interesting. this will require alot of experimentation on my part, but u gave the most coherent answer and i thank you for that! between what you and malk said i feel much more empowered now, i want to create some complicated animations so this basic understanding was kinda holding me back. its hard to find online tutorials that just dont default to setinterval/settimout for animations, theres very little in the way of what im trying to accomplish without using setinterval/settimout. – Ghoyos Aug 05 '16 at 17:59
  • Glad to help mate, happy coding :) – nem035 Aug 05 '16 at 18:02
2

You don't really need javascript for something like this. Keyframes let you define styles by percent complete. Using that you can time 2 animations for a similar result:

@keyframes progress {
  0% { width: 0px;}
  50% { width: 600px;}
  100% {width: 600px;}
}
@keyframes progress2 {
  0% { width: 600px;}
  49% { width:600px;}
  50% { width: 0px;}
  100% {width: 600px;}
}
div {
  width:600px;
  height:50px;
  background-color:black;
}
#rightBox {
  animation: progress 4s infinite;
}
#rightBoxTwo {
  animation: progress2 4s infinite;
}
<div id="rightBox"></div>
<div id="rightBoxTwo"></div>
Malk
  • 11,855
  • 4
  • 33
  • 32
  • oh wow very interesting, and the animation is buttery smooth to, but you used timing within css to infinitly run to diff animations. this will deff help with what im trying to do – Ghoyos Aug 05 '16 at 17:54