全屏菜单

一条时间线管「开」,reversed 管关。 不要分别写 openTl / closeTl 两套互相打架的动画。

const tl = gsap.timeline({ paused: true, reversed: true });
tl.set(overlay, { visibility: "visible", pointerEvents: "auto" })
  .fromTo(overlay, { yPercent: -100 }, { yPercent: 0, duration: 0.7, ease: "power4.inOut" })
  .from(overlay.querySelectorAll("a"), { y: 40, opacity: 0, stagger: 0.06 }, "-=0.35");

function toggle() { tl.reversed() ? tl.play() : tl.reverse(); }