Search code examples
javascriptgsap

Using async/await to pause GSAP Flip animation


I'm using GSAP's Flip plugin to animate a loading animation that goes from the corner of the screen to the center, and then back when the page is loaded. I thought a good way to do that would be to use async/await to pause the script until a hide_logo_animation bool is toggled.

This is my attempt (Using squares instead), but it does nothing. No errors so I don't know how to debug it.

What am I doing wrong here? I would expect it to flip the position of the two squares and wait for me to toggle hide_logo_animation before switching back.

<div class="container">
  <div class="square" id="sq1">1</div>
  <div class="square" id="sq2">2</div>
</div>
<script src="https://cdnjs.cloudflare.com/ajax/libs/gsap/3.7.1/gsap.min.js"></script>
<script src="https://assets.codepen.io/16327/Flip.min.js"></script>
body {
  background-color: #222;
  font-family: "Signika Negative", sans-serif, Arial;
}

.container {
  display: -webkit-box;
  display: flex;
  -webkit-box-pack: justify;
  justify-content: space-between;
}

.square {
  width: 100px;
  height: 100px;
  font-size: 3em;
  display: -webkit-box;
  display: flex;
  -webkit-box-pack: center;
          justify-content: center;
  -webkit-box-align: center;
          align-items: center;
  color: black;
  background-color: #88ce02;
  cursor: pointer;
}
gsap.registerPlugin(Flip);

var hide_logo_animation = false
showLogoAnimation(hide_logo_animation)

async function showLogoAnimation(hide_logo_animation) {
    const logo_state = Flip.getState("#sq1", {})
    Flip.from(logo_state, {
        targets: '#sq2',
        duration: 0.75,
        ease: "power1.inOut"
    })
    await hide_logo_animation
    const logo_animation_state = Flip.getState("#sq2", {})
    Flip.from(logo_animation_state, {
        targets: '#sq1',
        duration: 0.75,
        ease: "power1.inOut"
    })
}

Edit: Here is a Codepen/minimal example showing what I'm trying to do. The div word changes to 'Random' immediately, but I want it wait until I toggle the bool is_word_random.

I'm open to other methods as well. I would prefer to use a global event listener to wait for the value to change, but I couldn't find an example of a way to do that. The only way I found to listen for variable changes is get/set which I'm told is outdated, and that async/await should be used instead?

https://codepen.io/TheNomadicAspie/pen/qBmYEeJ

<div id="word">Word</div>
#word {
  font-size: 50px;
}
var is_word_random = false;
makeWordRandom();
waitFiveSeconds();

async function makeWordRandom() {
  await is_word_random;
  word.innerText = "Random";
}

function waitFiveSeconds() {
  setTimeout(() => {
    is_word_random = true;
  }, 5000);
}

Solution

  • In situations like this it helps to make more minimal demos of the core issue. In this case, perhaps this minimal JS code helps you understand the issue:

    let myBool = false;
    myFunc(myBool);
    
    async function myFunc(bool) {
      console.log(bool);
      await bool;
      console.log("This fires immediately");
    }
    

    As you can see, your await is just waiting on a variable that's a boolean type. await works with a promise (including ones made with Promise.all() or returned from a function). So that's your issue.

    If you want to use async/await I recommend calling the wait function from the makeWordRandom function and returning a promise from waitFiveSeconds: Demo.


    I'm not sure why you're wanting to use an async function here. I would probably call the first part of the function on load then the second part whenever you were planning on toggling the boolean. Like this:

    function showLogoAnimation() {
        const logo_state = Flip.getState("#sq1", {});
        Flip.from(logo_state, {
            targets: '#sq2',
            duration: 0.75,
            ease: "power1.inOut"
        });
    }
    
    function hideLogoAnimation() {
      const logo_animation_state = Flip.getState("#sq2", {});
      Flip.from(logo_animation_state, {
          targets: '#sq1',
          duration: 0.75,
          ease: "power1.inOut"
      });
    }
    
    showLogoAnimation();
    
    // Whenever you were changing the boolean, just call hideLogoAnimation() instead