You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何阻止GSAP函数隐藏NextUI导航栏?

问题描述

在Next.js项目中实现全屏滚动功能,使用GSAP ScrollTrigger完成了面板切换效果,但搭配NextUI导航栏组件时,即使已将导航栏的shouldHideOnScroll属性设为false,滚动到第二个全屏板块时导航栏仍会自动隐藏,推测是GSAP滚动脚本干扰了导航栏的滚动检测逻辑。

现有实现代码

JSX结构

<section class="description panel blue">
  <div>
    <h1>Layered pinning</h1>
    <p>Use pinning to layer panels on top of each other as you scroll.</p>
    <div class="scroll-down">Scroll down<div class="arrow"></div></div>
  </div>
</section>

<section class="panel red">
    ONE
</section>
<section class="panel orange">
    TWO
</section>
<section class="panel purple">
    THREE
</section>
<section class="panel green">
    FOUR
</section>

<header>
   <a href="https://greensock.com/scrolltrigger">
     <img class="greensock-icon" src="https://s3-us-west-2.amazonaws.com/s.cdpn.io/16327/scroll-trigger-logo-light.svg" width="200" height="64" />
  </a> 
</header>

GSAP脚本

gsap.registerPlugin(ScrollTrigger);

let scrollTween;

function goToSection(i) {
  scrollTween = gsap.to(window, {
    scrollTo: {y: i * innerHeight, autoKill: false},
    duration: 1,
    onComplete: () => scrollTween = null,
    overwrite: true
  });
}

gsap.utils.toArray(".panel").forEach((panel, i) => {
  ScrollTrigger.create({
    trigger: panel,
    start: "top bottom-=2",
    end: () => "+=" + (window.innerHeight * 2 - 4),
    onToggle: self => self.isActive && !scrollTween && goToSection(i)
  });
});

window.addEventListener("wheel", cancelWhenTweening, {passive: false});
window.addEventListener("scroll", cancelWhenTweening, {passive: false});
function cancelWhenTweening(e) {
  scrollTween && e.preventDefault();
}

CSS样式

html, body { height: auto; }
.panel {
  height: 100vh;
  position: sticky;
  top: 0;
}

解决方案

1. 修正GSAP滚动事件拦截逻辑

当前代码中同时拦截了wheel和scroll事件并阻止默认行为,导致NextUI无法捕获原生滚动状态。调整为仅在动画执行时拦截滚轮事件,保留原生scroll事件:

gsap.registerPlugin(ScrollTrigger);

let scrollTween;

function goToSection(i) {
  scrollTween = gsap.to(window, {
    scrollTo: {y: i * innerHeight, autoKill: false},
    duration: 1,
    onComplete: () => {
      scrollTween = null;
      // 动画完成后手动触发滚动事件,同步导航栏状态
      window.dispatchEvent(new Event('scroll'));
    },
    overwrite: true
  });
}

gsap.utils.toArray(".panel").forEach((panel, i) => {
  ScrollTrigger.create({
    trigger: panel,
    start: "top bottom-=2",
    end: () => "+=" + (window.innerHeight * 2 - 4),
    // 改用onEnter/onLeaveBack触发,减少误判
    onEnter: () => !scrollTween && goToSection(i),
    onLeaveBack: () => !scrollTween && goToSection(i)
  });
});

function cancelWhenTweening(e) {
  // 仅在滚轮事件且动画执行中时阻止默认行为
  if (scrollTween && e.type === 'wheel') {
    e.preventDefault();
  }
}

window.addEventListener("wheel", cancelWhenTweening, {passive: false});
// 移除scroll事件的拦截

2. 手动强制导航栏保持显示

如果上述调整后仍有问题,可在GSAP动画关键节点直接控制导航栏状态(以React项目为例):

import { useRef, useEffect } from 'react';
import { Navbar } from '@nextui-org/react';

export default function Layout() {
  const navbarRef = useRef(null);

  useEffect(() => {
    const syncNavbarState = () => {
      if (navbarRef.current) {
        // 强制导航栏保持可见,适配NextUI组件API
        navbarRef.current.setVisible(true);
      }
    };

    // 监听滚动事件,同步状态
    window.addEventListener('scroll', syncNavbarState);
    return () => window.removeEventListener('scroll', syncNavbarState);
  }, []);

  return (
    <Navbar ref={navbarRef} shouldHideOnScroll={false}>
      {/* 导航栏内容 */}
    </Navbar>
  );
}

3. 优化ScrollTrigger配置

指定滚动容器并关闭不必要的优化,确保滚动检测逻辑与NextUI兼容:

ScrollTrigger.create({
  trigger: panel,
  start: "top bottom-=2",
  end: () => "+=" + (window.innerHeight * 2 - 4),
  onEnter: () => !scrollTween && goToSection(i),
  onLeaveBack: () => !scrollTween && goToSection(i),
  // 指定滚动容器为window,避免上下文冲突
  scroller: window,
  // 关闭移动端尺寸忽略,确保滚动事件正常触发
  ignoreMobileResize: false
});

内容的提问来源于stack exchange,提问作者lesi

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.19 17:43:10