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

The Ubuntu virtual machine hosted on Google Cloud is experiencing difficulties connecting through Node.js using an external IP address

const express = require('express'); const bodyParser = require('body-parser'); const path = require('path'); const app = express(); app.listen(3000, function(){ console.log('Server is now live on port 3000' ...

Struggling to display the preloader animation while waiting for the render.com server to start up (using the free tier web service)

My choice for deploying dynamic websites is render.com and I am currently using their free tier. The issue with this free service is that Render spins down the web service after 15 minutes of inactivity, resulting in a delay when it needs to spin back up u ...

Generate fresh input fields with distinct identifiers using JavaScript

My challenge is to dynamically create new empty text boxes in JavaScript, each with a unique name, while retaining the text entered in the previous box. I struggled with this for a while and eventually resorted to using PHP, but this resulted in unnecessar ...

Guide on fetching live data from mysql database in angularjs

How can I dynamically load database users into a select box using Angular? <div ng-app="myapp" ng-controller="myctrl" class="centered"> <label>Select User</label> <select ng-model="selectedItem" ng-options="item.name for item in ...

HTML animation effect on subpage with a URL modification [LATEST UPDATE]

Can you smoothly load a new subpage in the background, update the URL, and fade it in while an animation is playing on the previous page? Check out this example (jsFiddle) to see a simple animation: $(document).ready(function() { 'use strict&apo ...

Retrieving HTML content from Wikipedia's API using JavaScript

I am encountering an issue where every time I attempt to log data to my console, an error occurs. Could someone kindly point out what may be the problem with the code? My objective is to actually showcase the html content on a webpage. Below is the code ...

Is there a way to add another item to a repeated DOM element without having to modify the ng-repeat scope?

I am working with a list of items using ng-repeat <div layout="column" class="md-whiteframe-1dp" ng-repeat="item in child.items track by item._id" id={{item._id}}child> </div> I am looking to add an additional DOM ele ...

Discover distinct and recurring elements

Having two sets of JSON data: vm.userListData = [{ "listId": 1, "permission": "READ" }, { "listId": 2, "permission": "WRITE" }, { "listId": 2, "permission": "READ" }, { "listId": 3, ...

Utilize AJAX JQuery to Transmit POST Data

I am facing an issue with sending the selected item from a Bootstrap dropdown to my controller using the POST method. Unfortunately, I am encountering difficulties in getting it to work. Within the dropdown, I am fetching records from the database and dis ...

What are the steps to modify the relative URL when using Express proxy?

To prevent the common CORS issue with client-side JavaScript code, I utilize a Node.js Express server. The server is configured with the following code: var app = express(); app.all('/Api/*', function (req, res) { proxy.web(req, res, { ...

Utilizing async await in a JavaScript event: A guide

I have coded the introduction page for my game, which includes a submit button and a textbox for users to input their username. Upon pressing the submit button, the code posts the name into a JSON file and retrieves all the data from the JSON file to sen ...

Click on another part of the page to reveal a dropdown menu

I am seeking a way to trigger the opening of this dropdown select not by directly clicking on its position, but rather by clicking on another <span>. Displayed below is the dropdown menu: <div class="styled-select"> <span id="camDurati ...

Determine the originating component in React by identifying the caller

Can you explain how to access the calling component in a React application? function MyCallingComponent() { return <MyReadingComponent/> } function MyReadingComponent() { console.log(callingComponent.state) } ...

Leveraging ng-click and ng-hide/show directives within ng-repeat in Angular

I have a simple Single Page Website built with Angular. I utilized ng-repeat to generate content on the main page, where each item is an image. I am looking to create an alternate view for each image to display more details. I have implemented this feature ...

Assistance with JSONP (Without the use of jQuery)

I've been putting in a lot of effort trying to understand how to make a JSONP request, but all the reference materials I find are full of jQuery examples. I can go through the jQuery source code, but I prefer a straightforward and simple example. I&ap ...

Share an entire /folder through an express server

I am currently working on an express server setup, and I am looking to streamline my route handling for managing an entire directory structure. root /html /css /js /app.js /images /index.html /some-other.htm ...

The TypeScript error occurs when attempting to assign a type of 'Promise<void | Object>' to a type of 'Promise<Object>' within a Promise.then() function

I'm currently working on a service to cache documents in base64 format. The idea is to first check sessionStorage for the document, and if it's not there, fetch it from IRequestService and then store it in sessionStorage. However, I've encou ...

Choose all from the list of categories

function CheckItems(chk) { if(document.myform.brandid.value!="Check all"){ for (i = 0; i < chk.length; i++) chk[i].checked = true ; document.myform.brandid.value="UnCheck all"; }else{ for ( ...

Issues arise when trying to use a JavaScript function within an HTML form, with an error message stating "TypeError: total

Recently, I encountered an issue with a straightforward JavaScript function that calculates user input. The function performed as expected when I tested it without the form tag. However, when I tried using the same code within the form tag, an error was di ...

Accessing geographical coordinates using Google Maps API with JavaScript

Hey there, I could really use your assistance. I'm looking to integrate a localization map on my website to track user locations. Any idea how I can go about doing this? Thanks in advance! ...