如何阻止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
相关产品推荐
相关产品推荐

