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

Next.js中GSAP横向滚动动画卡顿问题求助

解决Next.js中GSAP横向滚动动画卡顿问题

问题描述

在Next.js项目中使用GSAP实现横向滚动动画,动画可正常运行,但当scroll-section进入视口时出现卡顿,动画不流畅,调整pin属性后问题仍存在。

相关代码

React组件代码

import React, { useRef, useEffect } from "react";
import { gsap } from "gsap";
import { ScrollTrigger } from "gsap/dist/ScrollTrigger";
import styles from './scroll.style.css';

function ScrollSection() {
  const sectionRef = useRef(null);
  const triggerRef = useRef(null);

  gsap.registerPlugin(ScrollTrigger);

  useEffect(() => {
    const pin = gsap.fromTo(
      sectionRef.current,
      {
        translateX: 0,
      },
      {
        translateX: "-300vw",
        ease: "none",
        duration: 1,
        scrollTrigger: {
          trigger: triggerRef.current,
          start: "center center",
          end: "2000 top",
          scrub: 0.6,
          pin: true,
        },
      }
    );
    return () => {
      pin.kill();
      ScrollTrigger.getAll().forEach(trigger => trigger.kill());
    };
  }, []);

  return (
    <section className="scroll-section-outer">
      <div ref={triggerRef}>
       <h3 className="introduction">Mytext</h3>
       <div className="linea_div"><hr className="linea"/></div>
        <div ref={sectionRef} className="scroll-section-inner">
          <div className="scroll-section">
            <p className="Project_title">title1</p>
            <h3 className="scroll_gallery">Section 1</h3>
          </div>
          <div className="scroll-section">
          <p className="Project_title">title2</p>
            <h3 className="scroll_gallery">Section 2</h3>
          </div>
          <div className="scroll-section">
          <p className="Project_title">title3</p>
            <h3 className="scroll_gallery">Section 3</h3>
          </div>
          <div className="scroll-section">
          <p className="Project_title">title4</p>
            <h3 className="scroll_gallery">Section 4</h3>
          </div>
          <div className="scroll-section">
          <p className="Project_title">title5</p>
            <h3 className="scroll_gallery">Section 5</h3>
          </div>
        </div>
      </div>
    </section>
  );
}

export default ScrollSection;

CSS样式代码

.introduction {
  font-weight: 200;
  font-size: calc(1.675rem + 1.43158vw);
  line-height: 1.3em;
  letter-spacing: 0;
  color: #fff;
  padding-left: 20px;
}
.linea_div {
  padding-left: 20px;
  margin-bottom: 10px;
  padding-right: 20px;;
}
.linea {
  border: 1px solid #fff;
  width: 100%;
  margin:0;
  opacity: 0.5;
}
.scroll-section-outer {
  margin-top: 70px;
  overflow: hidden;
}

.scroll-section-inner {
  height: 50vh;
  width: 50vh;
  display: flex;
  flex-direction: row;
  position: relative;
  gap: 20px;
  padding: 20px;
}

.scroll-section {
  height: 50vh;
  justify-content: center;
  align-items: center;
  border-radius: 10px;
  display: grid;
}
.scroll_gallery {
  height: 45vh;
  width: 30vw;
  display: flex;
  justify-content: center;
  align-items: center;
  background-color: yellow;
  border-radius: 10px;
}
@media only screen and (max-width: 992px) {
  .scroll_gallery {
    width: 75vw;
  }
}

.scroll-section h3 {
  color: #fff;
  text-transform: uppercase;
}
.Project_title {
  color: #fff;
}

解决建议

1. 修正ScrollTrigger的滚动范围匹配

当前end: "2000 top"是固定像素值,无法匹配横向内容的实际长度,导致ScrollTrigger计算混乱。换成与动画位移对应的相对值:

scrollTrigger: {
  // ...其他属性
  end: "+=300vw", // 匹配translateX的-300vw,确保滚动范围与动画长度对应
}

2. 优化动画性能,开启硬件加速

  • 用GSAP原生x属性替代translateX,GSAP对该属性的性能优化更充分
  • 降低scrub值(建议0.3左右),过高的scrub会增加动画延迟
  • 给动画容器添加硬件加速提示

修改后的动画代码:

const pin = gsap.fromTo(
  sectionRef.current,
  { x: 0 },
  {
    x: "-300vw",
    ease: "none",
    duration: 1,
    scrollTrigger: {
      trigger: triggerRef.current,
      start: "center center",
      end: "+=300vw",
      scrub: 0.3,
      pin: true,
    },
  }
);

在CSS中添加:

.scroll-section-inner {
  /* ...原有样式 */
  will-change: transform;
  transform: translateZ(0); /* 强制开启硬件加速 */
}

3. 修复容器宽度溢出问题

当前scroll-section-inner的width: 50vh远小于内容总宽度,导致布局异常触发重排卡顿,计算正确的容器宽度:

.scroll-section-inner {
  /* ...原有样式 */
  width: calc(30vw * 5 + 20px * 6); /* 5个元素宽度 + 5个gap + 左右padding */
}

@media only screen and (max-width: 992px) {
  .scroll-section-inner {
    width: calc(75vw * 5 + 20px * 6);
  }
}

4. 完善ScrollTrigger清理逻辑

确保组件卸载时彻底销毁ScrollTrigger实例,避免内存泄漏:

return () => {
  pin.kill();
  ScrollTrigger.getAll().forEach(trigger => {
    if (trigger.vars.trigger === triggerRef.current) {
      trigger.kill();
    }
  });
};

5. 限制重排范围

给滚动容器添加contain属性,减少不必要的页面重排:

.scroll-section-inner {
  /* ...原有样式 */
  contain: layout paint;
}

内容的提问来源于stack exchange,提问作者Elia d'Albenzio

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.06 05:35:04