在前端动画开发中,滚动驱动(scroll-based)的交互方式越来越常见。通过简洁的代码实现“随着页面滚动播放动画”的效果。

这篇文章将以一个实际示例为基础,从零开始讲解 ScrollTrigger 的使用方法,包括滚动触发、动画同步、固定元素(pinning)等核心功能。

什么是 GSAP 和 ScrollTrigger?

  • GSAP(GreenSock Animation Platform) 是一个高性能的 JavaScript 动画库,用于创建精细控制的过渡动画。

  • ScrollTrigger 是 GSAP 提供的插件,用来让动画与滚动条同步进行。

ScrollTrigger 能做什么?简单说,它可以:

  • 监听页面滚动位置

  • 控制动画何时播放、播放多久

  • 让某个元素“固定在视口中”

  • 在滚动期间控制动画进度(scrub)

示例代码

我们来看一段完整的示例,了解如何实现滚动触发动画:

document.addEventListener("DOMContentLoaded", () => {
  gsap.registerPlugin(ScrollTrigger);
  ScrollTrigger.refresh();

  const anim1 = gsap.to(".a3-content-content-center", { width: 467, height: 662, paused: true });
  const anim2 = gsap.to(".a3-content-content-item-title", { opacity: 1, paused: true });

  ScrollTrigger.create({
    trigger: ".a3-content-t1",
    start: "-120px top",
    end: "+=100%",
    pin: ".area3 .layout-content",
    scrub: true,
    pinSpacing: false,
    markers: true,
    onUpdate: self => {
      let p = self.progress;
      anim1.progress(Math.min(p / 0.8, 1));
      anim2.progress(Math.min(p / 0.8, 1));
    },
  });
});

分析:每一行代码在做什么?

注册插件与刷新状态

gsap.registerPlugin(ScrollTrigger);
ScrollTrigger.refresh();
  • registerPlugin 用来启用 ScrollTrigger 插件。

  • refresh() 强制重新计算触发点,避免布局变化导致触发位置不准确。

创建两个动画(但先暂停)

const anim1 = gsap.to(".a3-content-content-center", {
  width: 467,
  height: 662,
  paused: true
});
const anim2 = gsap.to(".a3-content-content-item-title", {
  opacity: 1,
  paused: true
});
  • 这两个动画是提前定义好的。

  • 设置 paused: true,是为了让我们手动控制动画进度。

创建滚动触发器

ScrollTrigger.create({
  trigger: ".a3-content-t1",
  start: "-120px top",
  end: "+=100%",
  pin: ".area3 .layout-content",
  scrub: true,
  pinSpacing: false,
  markers: true,
  onUpdate: ...
});

参数

作用

trigger

指定触发滚动的目标元素

start

动画开始的位置,这里表示 .a3-content-t1 的顶部滚动到视口顶端向上 120px 处时开始

end

滚动 100% 的屏幕高度后动画结束

pin

将 .layout-content 固定在视口中

scrub: true

开启滚动同步(滚动多少,动画走多少)

pinSpacing: false

取消 ScrollTrigger 自动插入的额外空白区域

markers: true

开启调试标记,显示 start/end 位置

如何让动画“提前完成”?

观察这一段代码:

onUpdate: self => {
  let p = self.progress;
  anim1.progress(Math.min(p / 0.8, 1));
  anim2.progress(Math.min(p / 0.8, 1));
}
  • self.progress 是当前滚动进度,范围是 0 ~ 1。

  • 我们将 progress 除以 0.8,再 Math.min(..., 1),意思是:

    动画将在滚动到 80% 的位置时就完全播放完毕,之后不再继续。

这样做的好处是,可以让动画提前结束,后面剩下的滚动空间保持动画终态,提升视觉节奏控制。

开启 markers,轻松调试

将 markers: true 添加到 ScrollTrigger 中,可以看到页面上出现绿色和红色的线:

  • start 绿色线表示动画开始点

  • end 红色线表示动画结束点

这对调试非常有帮助。

小结:ScrollTrigger 核心概念汇总

概念

描述

trigger

哪个元素决定动画的滚动时机

start / end

动画的滚动范围(什么时候开始、多久结束)

scrub

滚动与动画同步进行

pin

固定某个元素在滚动过程中不动

onUpdate

每次滚动时调用,可动态控制动画

progress

当前滚动进度(0~1)

pinSpacing

是否插入空白空间撑开 layout(可关闭)

paused: true

手动控制动画,而非自动播放

参考链接

https://codepen.io/GreenSock/pen/xxVWJGe