Human Friend
Human Friend

Reputation: 175

How do I wait for this animation to finish before moving on to the next one?

I am creating a game with HTML, CSS, & JavaScript. I have 5 h2(s) and I want to wait for the animation to finish before moving on to any part of the code. The animation works how I want it to but the JavaScript is starting the next animation before the first one is even done! I have tried using

window.setTimeOut

but no luck. Here is the code with the required code: https://codepen.io/HumanFriend/pen/mdOBvoL Can someone help me?

Upvotes: 5

Views: 15813

Answers (3)

ankhzet
ankhzet

Reputation: 2568

It might be worthy of note, that animationend/transitionend events are emitted for every animated element in the element tree you attach the listeners to:

#parent:hover {
  transition: ... 0.5s;
}
#child:hover {
  transition: ... 0.2s;
}
<div id="parent">
  <div id="child">Hover me</div>
<div>
...
parent.addEventListener('animationend', (event) => {
  console.log('animated', event.target);
});
animated div#child
animated div#parent

As such, if you make an animated container that can have animated children, then you should account for event bubbling:

dialog.addEventListener('close', closeHandler);
dialog.addEventListener('transitionend', animationHandler);

let returnValue;
const closeHandler = () => {
  returnValue = ...;
};
const animationHandler = ({ target }) => {
  // make sure it's the dialog that ended animating,
  // and not some button's 'onblur' animation
  if (target === dialog) {
    onClose(returnValue);
  }
};

Upvotes: 0

Jeffhowcodes
Jeffhowcodes

Reputation: 416

To elaborate on entio's answer, your animation occurs when an element has the class "typing-effect." When that animation ends, the browser calls an event called "animationend." You can use JavaScript to run your animation on the next element by accessing that event.

Notice in HTML the snippit below, I've moved the "display: hidden" to a CSS class and removed the "typing-effect." In my JavaScript function, I enable the class in the first element, increment the counter, and told the "animationend" to call the function again with the new value for "i."

Edit: I forgot to mention, I modified the id values. I don't believe a valid id value in HTML5 can contain parenthesis.

console.log("script.js connected");

let iLevel = 1;
let loop = 0;

function animateNext(i){
  let stop = document.querySelectorAll('.animated').length;
  let animated = document.querySelector(`#h2_${i}`);
  animated.classList.add('typing-effect');

  animated.addEventListener('animationend', () => {
    if(i===stop){
      iLevel = "iDone";
    }else{
      animateNext(i+1);
    }
  });
}

function startGame() {
  animateNext(1);
}
.animated{
  display: none;
}
.typing-effect {
  display: block;
  animation: typing-effect 5s steps(130, end), 0.75s step-end infinite;
  white-space: nowrap;
  overflow: hidden;
  border-right: 2px solid black;
}
.typing-effect:after {
  content: " ";
}
@keyframes typing-effect {
  0% {
    width: 0%;
  }
  100% {
    width: 100%;
  }
}
@keyframes blink-caret {
  from,
  to {
    border-color: transparent;
  }
  50% {
    border-color: black;
  }
}
<button onclick="startGame();">START GAME</button>

<div id="instructions">

  <div>
    <h2 id="h2_1" class="animated">Welcome to The Number Wizrd</h2>
  </div>

  <div>
    <h2 id="h2_2" class="animated">Adjfosdf</h2>
  </div>
  <div>
    <h2 id="h2_3" class="animated">sosidjfs</h2>
  </div>
  <div>
    <h2 id="h2_4" class="animated">difjspodf</h2>
  </div>
  <div>
    <h2 id="h2_5" class="animated">skidjfosidf</h2>
  </div>

</div>

Upvotes: 2

entio
entio

Reputation: 4263

You can listen to animationend event, fe:

const animated = document.querySelector('.animated');

animated.addEventListener('animationend', () => {
  console.log('Animation ended');
});

Read more: https://developer.mozilla.org/en-US/docs/Web/API/HTMLElement/animationend_event


Random thing:

When you use setTimeout(nextI_ifelse(), 5000); you just invoke the nextI_ifelse inline (and you're setting timeout for the value returned from this function). Change it to setTimeout(nextI_ifelse, 5000);

Any you just want to read about algorithms in general. What you try to do makes sense, but the way you're trying to achieve that does not. The for loop in your codepen runs instantly, so iLevel is directly set to the last value.

Upvotes: 7

Related Questions