Katy O
Katy O

Reputation: 35

How to execute multiple animations at once

I am using two functions to Fade In/Fade Out an element. I know that both of the functions work correctly, and when I test them sequentially in the Console, they do what I want.

But

fadeIn()
fadeOut()

appears to make them both execute at the same time.

function fadeIn(el) {
      el.style.opacity = 0;
      el.style.display = 'block';

      var tick = function() {

        el.style.opacity = +el.style.opacity + 0.01;


        if (+el.style.opacity < 1) {
          (window.requestAnimationFrame && requestAnimationFrame(tick)) || setTimeout(tick, 2500)
        }
      };

      tick();
}

function fadeOut(el) {
  el.style.opacity = 1;

  var tickOut = function() {
    el.style.opacity = +el.style.opacity - 0.01;


    if (+el.style.opacity > 0) {
      (window.requestAnimationFrame && requestAnimationFrame(tickOut)) || setTimeout(tickOut, 2500)
    }
    else if (+el.style.opacity === 0){
    el.style.display = 'none';
    }
  };

  tickOut();
}

Link to JsFiddle: https://jsfiddle.net/cwu9sg3h/

Edit: Expected Result is that the quote Fades In then fades out, then it switches to another quote which fades in/fades out. It never stops rotating out quotes.

Edit #2: I cannot use jQuery for this project!

Upvotes: 0

Views: 78

Answers (2)

bigblind
bigblind

Reputation: 12867

When you call fadeIn and fadeOut, immediately after eachother, they both register their tick function to be called on the next frame//tick (depending on whether requestAnimationFrame is supported.)

In order to run the animations in sequence, you'd have to know when fadeIn finishes, so you can start fading it out. If you're always fading out after fading in, you can call fadeOut inside fadeIn, like this:

var f;
if (+el.style.opacity < 1) {
    f = tick;
} else {
    f = fadeOut;
}
(window.requestAnimationFrame && requestAnimationFrame(f)) || setTimeout(f, 2500)

So you use this instead of the if statement you currently have in fadeIn.

If you want to make fadeIn more reusable, you could use a callback instead.

function fadeIn(el, callback) {
  el.style.opacity = 0;
  el.style.display = 'block';

  var tick = function() {

    el.style.opacity = +el.style.opacity + 0.01;
    if (+el.style.opacity < 1) {
      (window.requestAnimationFrame && requestAnimationFrame(tick)) || setTimeout(tick, 2500)
    }else{
        callback(el)
    }
  };

  tick();
}

Then, you can call it as fadeIn(el, fadeOut);.

Here's an example of it in action.

function fadeIn(el, callback) {
  el.style.opacity = 0;
  el.style.display = 'block';

  var tick = function() {

    el.style.opacity = +el.style.opacity + 0.01;
    if (+el.style.opacity < 1) {
      (window.requestAnimationFrame && requestAnimationFrame(tick)) || setTimeout(tick, 2500)
    }else{
        callback(el)
    }
  };

  tick();
}

function fadeOut(el) {
  el.style.opacity = 1;

  var tickOut = function() {
    el.style.opacity = +el.style.opacity - 0.01;


    if (+el.style.opacity > 0) {
      (window.requestAnimationFrame && requestAnimationFrame(tickOut)) || setTimeout(tickOut, 2500)
    }
    else if (+el.style.opacity === 0){
    el.style.display = 'none';
    }
  };

  tickOut();
}

var el = document.getElementById("quote");
var btn = document.getElementById("btn");
btn.addEventListener("click", function(){
  fadeIn(el, fadeOut);;
});
/* The CSS isn't important here. */
q{background-color: yellow;opacity:0;}
<q id="quote">"I'll appear and then disappear."</q><br>
<button id="btn">Click me to fade the quote in and out.</button>

Upvotes: 2

guest271314
guest271314

Reputation: 1

Define a variables to reference requestAnimation calls. Call cancelAnimationFrame at else block within fadeIn, fadeOut. Call fadeIn within displayTestimonials. Call fadeOut after call to cancelAnimationFrame within fadeIn else block. Call displayTestimonials within fadeOut else block.

nextIndex does not appear to be utilized. Substitute

  nextIndex = randomNumber();
  while (currentIndex == nextIndex) {
    currentIndex = randomNumber();
  }

for current while loop. Note, the current while loop does not prevent same element from being selected twice in succession.

    var testimonials = document.querySelectorAll('#testimonials span');
     //set a starting index of 0

     //Start displaying testimonials

    function randomNumber() {
      return Math.floor(testimonials.length * Math.random());
    }

    var index = randomNumber();

    displayTestimonial(index, fadeOut);

    function displayTestimonial(currentIndex) {
      //Check to see if we need to reset back to the first index
      nextIndex = randomNumber();
      while (currentIndex == nextIndex) {
        currentIndex = randomNumber();
      }
      console.log(testimonials[currentIndex]);
      //Display a testmonial and when testimonial is complete fade it out
      fadeIn(testimonials[currentIndex]);

      // callback(testimonials[currentIndex]);

    }

    function fadeIn(el) {
      el.style.opacity = 0;
      el.style.display = 'block';
      var raf;
      var tick = function() {

        el.style.opacity = +el.style.opacity + 0.01;


        if (+el.style.opacity < 1) {
          (window.requestAnimationFrame && (raf = requestAnimationFrame(tick))) || setTimeout(tick, 2500)
        } else {      
          cancelAnimationFrame(raf);
          console.log("fadeIn complete");
          fadeOut(el)
        }
      };

      tick();
    }

    function fadeOut(el) {
      el.style.opacity = 1;
      var raf1;
      var tickOut = function() {
        el.style.opacity = +el.style.opacity - 0.01;


        if (+el.style.opacity > 0) {
          (window.requestAnimationFrame && (raf1 = requestAnimationFrame(tickOut))) || setTimeout(tickOut, 2500)
        } else if (+el.style.opacity === 0) {
          // el.style.display = 'none';
          cancelAnimationFrame(raf1);
          console.log("fadeOut complete");
          index = randomNumber();
          displayTestimonial(index);
        }
      };

      tickOut();
    }
#testimonials {
  border-top: solid 1px #000;
  border-bottom: solid 1px #000;
  padding: 10px;
  text-align: center;
  margin: 10px;
}

#testimonials span {
  margin: 0;
  padding: 0;
}

#testimonials span {
  list-style-type: none;
  font-size: 24px;
  color: #001346;
  position: relative;
  margin: 0;
  animation: mymove 5s infinite;
  opacity: 1;
  animation-delay: 15s;
  /**ADD THIS TO CSS*/
  display: none;
}

#testimonials span a {
  display: block;
  padding: 5px;
  background-color: #EF681F;
  color: #FFF;
  margin-top: 5px;
  font-size: 16px;
  width: 140px;
  margin-left: auto;
  margin-right: auto;
}

#testimonials span a:hover {
  text-decoration: none;
  background-color: #001346;
}

@keyframes fadeIn {
  to {
    opacity: 1;
  }
}

#testimonials span {
  display: none;
}
<div id="testimonials">
  <span>"Testimonials can be very powerful for helping to establish trust and encouraging visitors to take whatever action you are after."
            <a href = "#">Register</a></span>
  <span>"Lorem ipsum dolor sit amet, consectetuer adipiscing elit. Aenean commodo ligula eget dolor. Aenean massa."
            <a href = "#">Register</a></span>
  <span>"Sed ut perspiciatis unde omnis iste natus error sit voluptatem accusantium doloremque laudantium, totam rem aperiam, eaque."
            <a href = "#">Register</a></span>
</div>

jsfiddle https://jsfiddle.net/cwu9sg3h/12/

Upvotes: 1

Related Questions