简体   繁体   中英

Why is the animation not reversed in GSAP?

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. Find my code below and here a Codepen link.

 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 class="toggler"> <div class="hamburger"> <div class="line one"></div> <div class="line two"></div> <div class="line three"></div> </div> <p>Menu</p> </div> <div class="nav-menu"> <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>

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 class="toggler"> <div class="hamburger"> <div class="line one"></div> <div class="line two"></div> <div class="line three"></div> </div> <p>Menu</p> </div> <div class="nav-menu"> <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>

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

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

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM