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

点击GSAP动画中的React Router Link致网站崩溃求助

问题

我用GSAP给项目板块实现了横向滚动动画,但遇到了问题:点击正在执行GSAP动画的项目时,作品集网站崩溃。React Router的Link标签已经切换了URL,但路由配置的组件未渲染,页面呈空白状态。我使用了LocomotiveScroll,并通过自定义Hook使其兼容GSAP的ScrollTrigger。怀疑是路由切换时LocomotiveScroll保留了新页面不存在的滚动位置导致的问题,控制台无报错,求解决建议。

相关代码

项目链接组件代码

<Link
  to={`/projects/${project.id}`}
  className={styles.link}
  id='link'
>
  <div
    id='projectImageContainer'
    className={styles.projectImageContainer}
    onMouseEnter={() => setHover(true)}
    onMouseLeave={() => setHover(false)}
  >
    {/* <AnimatedImage src={project.image} playAnim={hover} /> */}
  </div>
</Link>

GSAP横向滚动动画代码

useEffect(() => {
    gsap.registerPlugin(ScrollTrigger);

    const scrollContext = gsap.context(() => {
      scrollTl.current = gsap.timeline({
        scrollTrigger: {
          trigger: projectsContainerRef.current,
          scroller: '.App',
          start: 'top top',
          end: `+=${trackRef.current.offsetWidth}`,
          pin: true,
          scrub: 0.5,
        },
      });

      scrollTl.current
        .to(trackRef.current, {
          xPercent: -100,
          ease: 'none',
        })
        .to(
          titleRef.current,
          {
            xPercent: -50,
            ease: 'none',
          },
          '<'
        );
    });

    return () => scrollContext.revert();
  }, []);

解决建议

  • 路由切换前清理GSAP与ScrollTrigger实例:在组件卸载或路由跳转时,除了调用scrollContext.revert(),还要手动销毁所有ScrollTrigger实例,同时终止GSAP时间线:

    // 在组件卸载的清理函数或路由跳转事件中执行
    scrollTl.current?.kill();
    ScrollTrigger.getAll().forEach(trigger => trigger.kill());
    

    残留的动画实例会尝试操作已卸载的DOM元素,引发静默异常导致页面崩溃。

  • 重置LocomotiveScroll滚动位置:通过React Router的useLocation监听路由变化,在新页面挂载时调用LocomotiveScroll的scrollTo(0)方法,强制回到页面顶部,避免旧页面的滚动偏移量被带到新页面:

    import { useLocation } from 'react-router-dom';
    import locomotiveScroll from '../path/to/your/locomotive/instance';
    
    useEffect(() => {
      locomotiveScroll.scrollTo(0, { immediate: true });
    }, [location.pathname]);
    
  • 点击Link时暂停动画:给Link添加onClick事件,先暂停当前GSAP动画再执行路由跳转,避免动画在DOM切换过程中仍在操作元素:

    <Link
      to={`/projects/${project.id}`}
      className={styles.link}
      id='link'
      onClick={() => scrollTl.current?.pause()}
    >
      {/* 子元素 */}
    </Link>
    
  • 检查ScrollTrigger的scroller配置:当前ScrollTrigger使用.App作为scroller,若路由切换后该容器的结构或存在状态发生变化,会导致ScrollTrigger失效。可将scroller替换为更稳定的根容器,或在路由切换时重新初始化ScrollTrigger。

  • 监听路由变化清理动画上下文:在项目列表组件中,通过useLocation监听路径变化,当路径离开项目列表页时,彻底清理GSAP上下文和相关实例:

    import { useLocation } from 'react-router-dom';
    
    useEffect(() => {
      const scrollContext = gsap.context(() => {
        // 初始化动画逻辑
      });
    
      const cleanup = () => {
        scrollContext.revert();
        scrollTl.current?.kill();
        ScrollTrigger.getAll().forEach(trigger => trigger.kill());
      };
    
      return cleanup;
    }, [location.pathname]);
    

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.22 06:32:03