Home > Blockchain >  Why is the animation not reversed in GSAP?
Why is the animation not reversed in GSAP?

Time:06-09

I have question, I wanted reverse animation "showMenuList" (this is pink background), but this not working, where is the mistake?

I tried paused, and so many method but this not working, please help

I know that this is mostly code but I don't know what else to write.

const menuToggler = document.querySelector(".toggler");
const menuTogglerHamburger = document.querySelector(".toggler .hamburger");

menuToggler.addEventListener("click", function () {
  //checking if there is a class animationToggler
  if (menuTogglerHamburger.classList.contains("animationToggler")) {
    //restart animation rotate
    menuTogglerHamburger.classList.remove("animationToggler");
    void menuTogglerHamburger.offsetWidth;
    menuTogglerHamburger.classList.add("animationToggler");
  }

  menuTogglerHamburger.classList.add("animationToggler");

  menuToggler.classList.toggle("show");
  menuToggler.classList.contains("show")
    ? showMenuList(true)
    : showMenuList(false);

  setTimeout(() => {
    //animation line on the cross
    menuTogglerHamburger.classList.toggle("active");
  }, 200);
});

//---------------------- Show menu list ----------------------//

const showMenuList = (e) => {
  console.log(e);
  const showMenuTl = gsap.timeline({ pause: true });

  e ? showMenuTl.play() : showMenuTl.reverse();

  showMenuTl
    .to(".nav-menu", 0.8, { css: { top: "50%" } })
    .to(".nav-menu", 0.4, { css: { width: "140vw", height: "140vw" } });
};
body {
    overflow: hidden;
}

nav {
    display: flex;
    width: 100%;
    align-items: center;
    justify-content: space-around;
    padding-top: 1em;
}

.toggler {
    display: flex;
    align-items: center;
    cursor: pointer;


}

.animationToggler {
    animation: animationTogglerMenu .8s ease;
}


.toggler p {
    margin: 0;
    text-transform: uppercase;
    font-size: 1.65rem;
    margin: 0 0 0 10px;
    z-index: 3;
}

.hamburger {
    z-index: 3;
}

.hamburger .line {
    height: 4px;
    width: 2.5em;
    background: #000;
    margin: .45em 0;
    border-radius: 50px;
    transition: .3s;
}

.active .one {
    transform: rotate(45deg) translateY(15px);
}

.active .two {
    background-color: transparent;
    transition: none;
}

.active .three {
    transform: rotate(-45deg) translateY(-15px);
}

.nav-menu {
    position: absolute;
    top: -100%;
    left: 50%;
    transform: translate(-50%, -50%);
    width: 3em;
    height: 3em;
    background-color: rgb(255, 117, 117);
    border-radius: 50%;
    /* opacity: 0.4; */
    z-index: 2;
}

.nav-menu ul {
    display: none;
}


@keyframes animationTogglerMenu {

    100% {
        transform: rotate(360deg);
    }
}
<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
    <link rel="stylesheet" href="style.css">
</head>

<body>
    <div >
        <div >
            <div ></div>
            <div ></div>
            <div ></div>
        </div>
        <p>Menu</p>
    </div>
    <div >
        <ul>
            <li><a href="#">Home</a></li>
            <li><a href="#">Projekty</a></li>
            <li><a href="#">O nas</a></li>
            <li><a href="#">Kontakt</a></li>
        </ul>
    </div>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/gsap/3.10.4/gsap.min.js"></script>
    <script src="main.js"></script>
</body>

</html>

https://codepen.io/jarek-babiak/pen/KKQGgME

CodePudding user response:

One issue with your code is you need to pass paused: true instead of pause:true to the timeline function.

One way you could improve your code (in my opinion) is to move the creation of your timeline object to the top level of your code block. Like so...

const menuToggler = document.querySelector(".toggler");
const menuTogglerHamburger = document.querySelector(".toggler .hamburger");

// Add it here -----------------------
const showMenuTl = gsap.timeline({ paused: true });
showMenuTl
  .to(".nav-menu", 0.8, { css: { top: "50%" } })
  .to(".nav-menu", 0.4, { css: { width: "140vw", height: "140vw" } });

Then you can get rid of the showMenuList function and call play and reverse directly.

  menuToggler.classList.toggle("show");
  menuToggler.classList.contains("show")
    ? showMenuTl.play()
    : showMenuTl.reverse()

CodePudding user response:

One way you could approach this is creating another timeline. Which would be annoying to deal with if you added more keyframes. Another way you could do this is by adding a starting keyframe and then everything should run smoothly as shown below.

showMenuTl
  .to(".nav-menu", 1, { css: { width: "3rem", height: "3rem", top: "-100%" } })
    .to(".nav-menu", 0.8, { css: { width: "3rem", height: "3rem", top: "50%" } })
    .to(".nav-menu", 0.4, { css: { width: "140vw", height: "140vw", top: "50%" } });

  e ? showMenuTl.play() : showMenuTl.reverse(0);

CodePudding user response:

First, it should be { paused: true }, not { pause: true }, as @jessegavin said. Second, at the point where the click happens, you should have already made up the animation, which means the timeline definition should be at the top, outside of showMenuList. Third, you could simplify your code to this:

See the JavaScript part, it's way more short, I slightly modified the CSS.

const menuToggler = document.querySelector(".toggler");

const showMenuTl = gsap.timeline({ paused: true });
showMenuTl
  .to(".nav-menu", 0.8, { css: { top: "50%" } })
  .to(".nav-menu", 0.4, { css: { width: "140vw", height: "140vw" } });

menuToggler.addEventListener("click", function () {
  if (menuToggler.classList.contains("active")) {
    menuToggler.classList.remove("active");
    showMenuTl.reverse();
  } else {
    menuToggler.classList.add("active");
    showMenuTl.play();
  }
});
body {
  overflow: hidden;
}

nav {
  display: flex;
  width: 100%;
  align-items: center;
  justify-content: space-around;
  padding-top: 1em;
}

.toggler {
  display: flex;
  align-items: center;
  cursor: pointer;
}

.toggler p {
  margin: 0;
  text-transform: uppercase;
  font-size: 1.65rem;
  margin: 0 0 0 10px;
  z-index: 3;
}

.hamburger {
  z-index: 3;
}

.hamburger .line {
  height: 4px;
  width: 2.5em;
  background: #000;
  margin: 0.45em 0;
  border-radius: 50px;
  transition: 0.3s;
}
.active .hamburger {
  animation: animationTogglerMenu 0.8s ease;
}
.active .one {
  transform: rotate(45deg) translateY(15px);
}

.active .two {
  background-color: transparent;
  transition: none;
}

.active .three {
  transform: rotate(-45deg) translateY(-15px);
}

.nav-menu {
  position: absolute;
  top: -100%;
  left: 50%;
  transform: translate(-50%, -50%);
  width: 3em;
  height: 3em;
  background-color: rgb(255, 117, 117);
  border-radius: 50%;
  /* opacity: 0.4; */
  z-index: 2;
}

.nav-menu ul {
  display: none;
}

@keyframes animationTogglerMenu {
  100% {
    transform: rotate(360deg);
  }
}
<!DOCTYPE html>
<html lang="en">

<head>
  <meta charset="UTF-8">
  <meta http-equiv="X-UA-Compatible" content="IE=edge">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>Document</title>
  <link rel="stylesheet" href="style.css">
</head>

<body>
  <div >
    <div >
      <div ></div>
      <div ></div>
      <div ></div>
    </div>
    <p>Menu</p>
  </div>
  <div >
    <ul>
      <li><a href="#">Home</a></li>
      <li><a href="#">Projekty</a></li>
      <li><a href="#">O nas</a></li>
      <li><a href="#">Kontakt</a></li>
    </ul>
  </div>
  <script src="https://cdnjs.cloudflare.com/ajax/libs/gsap/3.10.4/gsap.min.js"></script>
  <script src="main.js"></script>
</body>

</html>

  • Related