Mastering the art of simultaneously running multiple animations

Utilizing two functions to apply a Fade In/Fade Out effect on an element. Confident in the functionality of both functions, as testing them sequentially in the Console proves their effectiveness.

However, executing:

fadeIn()
fadeOut()

seems to result in both operations occurring simultaneously.

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

Access JsFiddle link here: https://jsfiddle.net/cwu9sg3h/

Edit: Intended outcome involves quote fading in, followed by a fade out, transitioning to another quote with the same effect. Process is set to rotate quotes continuously.

Edit #2: jQuery not viable for this specific project!

Answer №1

When using the fadeIn and fadeOut functions one after the other, they both set their tick function to execute on the next frame/tick (depending on support for requestAnimationFrame).

To ensure that the animations run sequentially, it is necessary to determine when fadeIn completes so that fadeOut can be triggered. If you always want to fade out after fading in, you can place the call to fadeOut inside the fadeIn function, like this:

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

This approach replaces the conditional if statement currently used in fadeIn.

If you wish to make fadeIn more versatile, you can incorporate 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 invoke it as fadeIn(el, fadeOut);.

Here's an example demonstrating its functionality.

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 styling is not significant for this demonstration. */
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>

Answer №2

Establish variables to refer to requestAnimation calls. Invoke cancelAnimationFrame within the else block of both fadeIn and fadeOut. Call fadeIn inside displayTestimonials. After calling cancelAnimationFrame in the else block of fadeIn, call fadeOut. Within the else block of fadeOut, call displayTestimonials.

nextIndex is not being utilized effectively. Consider replacing

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

with a new logic for the current while loop. Keep in mind that the current loop currently does not prevent the 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/

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

On-page refresh triggering HTTP 404 error in Vue3 routing situation

Issue Upon reloading a route, such as /installer, in Vue3.js, I encounter the following error: Code Snippet I am utilizing the Router with the setup below: const router = createRouter({ history: createWebHistory(process.env.BASE_URL), routes, }); E ...

Error in test runner: Cannot convert type 'Cucumber' to type '? extends Runner' in Java cucumber

I'm currently working on setting up the Cucumber framework using Java for running my tests, but encountering a type mismatch error in the Test Runner. package cucumbertest; import org.junit.runner.RunWith; import cucumber.api.CucumberOptions; import ...

Angular: promptly exit out of ngClick event handler

I have a selection menu on my webpage that is essentially an unordered list, with each item in the menu formatted like this: <li ng-click='doCalc(5)'>Five</li> The doCalc function that is triggered by clicking on these items may tak ...

Retrieve the next 14 days starting from the current date by utilizing Moment.js

Looking to display the next 14 days in a React Native app starting from today's date. For example, if today is Friday the 26th, the list of days should be: 26 - today 27 - Saturday 28 - Sunday 01 - Monday 02 - Tuesday ............ 12 - Friday Is ther ...

What is the best way to remove data from both arrays simultaneously?

I am working with a grid that displays a list of time ranges. For example: timeList=[{from:12:00:00 , to:14:00:00 ,id:10}{from:08:00:00 , to:09:00:00 ,id:11{from:05:00:00 , to:10:00:00 ,id:12}}] time=[{Value:12:00:00 id:10} {Value:14:00:00 id:100} ...

hiding html elements by using the display property set to none instead of physically removing

I am currently utilizing an if-else statement to display different HTML structures. As a result, the entire HTML is being rendered twice. Is there a way we can utilize 'display: none' instead? I attempted to use it in th ...

leveraging the situation and a clever opening

Currently, I'm diving into mastering the proper utilization of context and hooks. Initially, everything worked flawlessly while all components remained within a single class. However, troubles arose when I segregated them into multiple classes leading ...

Error encountered while making an http get request for a node that returns JSON

I've been struggling with this issue for quite some time now. While I've come across similar problems on Stack Overflow, none of the suggested solutions seem to work for me. I keep encountering the following error message: undefined:1 SyntaxErro ...

Steps to troubleshoot the TypeError: cv.Mat is not a constructor in opencv.js issue

Encountering a problem while trying to use opencv.js for detecting aruco markers from my camera. Each time I attempt to utilize the method let image = new cv.imread('img'); An error keeps popping up: TypeError: cv.Mat is not a constructor ...

How do I iterate through my state in React Redux?

Currently, I am delving into Redux by creating a to-do list in React. I have been pondering on the utilization of the map function to iterate over the state so that I can display the data stored within different div elements. Here is my initial state: cons ...

Error with declaring TypeScript class due to private variable

When defining a TypeScript class like this: export class myClass { constructor(public aVariable: number) {} private aPrivateVariable: number; } and trying to initialize it with the following code: let someVar: myClass[] = [{ aVariable: 3 }, { aV ...

Selenium is encountering a maximum call stack size error while attempting to access Highcharts

This particular issue is a bit complex. My goal is to retrieve highchart data from a selenium-controlled Chrome browser using the driver.execute_script method and injecting some JavaScript: driver.execute_script("return $('#chartID').highcharts( ...

Utilize Postman to send a JSON body in a POST request to trigger a stored procedure on Microsoft SQL Server

I need to send a JSON request using the Postman app, utilizing the POST method to retrieve data. My boss, who is overseeing my training, assigned me this task. I've scoured the web for a week but haven't found a solution yet. Initially, I sugges ...

Is there a way to implement a css/javascript property specifically for a div that is selected in the url?

Take for instance the scenario where I possess the URL example.com/#foo. In this case, CSS styling will be directed to the div with the id foo. If achieving this solely in CSS is not feasible, what methods in JavaScript or jQuery can be used efficiently ...

Exploring the possibilities of reading and writing data in localStorage?

Just starting out with Phonegap, jQuery Mobile, and HTML5 - so please bear with me as I navigate through this learning process! I'm having an issue and could use some help. When trying to use a variable from localStorage, the screen remains blank whe ...

Ways to verify whether a string has already been hashed in Node.js utilizing crypto

I am currently working on an application that allows users to change their passwords. For this project, I am utilizing Node.js along with the mongoose and crypto libraries. To generate hashes for the passwords, I have implemented a hook into the model&ap ...

Sharing details of html elements using ng-click (AngularJS)

I am currently exploring options to enable users to click on a "open in new tab" link, which would essentially transfer that HTML element into a fresh window for their convenience. I am seeking advice on how to achieve this. At the moment, I am able to la ...

Using regular expressions to extract substrings from URL

I have different URL routes, such as var url = '/product' and '/product/create'. Is there a way to use Regex in order to extract only the route name like 'product'? ...

When an import is included, a Typescript self-executing function will fail to run

Looking at this Typescript code: (()=> { console.log('called boot'); // 'called boot' })(); The resulting JavaScript is: (function () { console.log('called boot'); })(); define("StockMarketService", ["require", "exp ...

Use jQuery to apply a class to some input elements when certain events like keyup or

If I type something in the input field, it should add a border to the li tag containing the text. The current script works fine, but is there a way to make this jQuery script shorter? Thank you for your help! .add_border{ border: 2px solid #000 !impor ...