滚动触发

ScrollTrigger

ScrollTrigger 滚动动画 滚动驱动动画 Scroll Animation Scrollytelling 视差滚动

GSAP 的滚动插件:元素滚入视口时触发动画,或用 scrub 把动画进度直接绑定到滚动位置,还能固定元素做分段叙事。

又称:滚动动画 · 滚动驱动动画 · Scroll Animation · Scrollytelling · 视差滚动

  • GSAP
  • Claude / Cursor

↓ 在框内向下滚动

↑ 向上滚动,动画会倒放

scrollTrigger: { scrub: 0.6, start: 'top 80%', end: 'bottom 20%' }

Prompt 片段

  • Claude / Cursor
    用 GSAP ScrollTrigger 做一个产品介绍区:section 进入视口时 pin 住,内部 timeline 依次展示三张图,scrub: 1,end: '+=2000',开发时打开 markers。
  • Claude / Cursor记得先 gsap.registerPlugin(ScrollTrigger)
    给页面里所有 .reveal 元素加滚动入场:从 y: 40、opacity: 0 进入,start: 'top 85%',toggleActions: 'play none none reverse',用 gsap.utils.toArray 批量创建。
  • Claude / Cursor
    让一个方块随滚动从左移动到右并旋转 360 度,scrub: 0.6,start: 'top 80%',end: 'bottom 20%',ease 设为 none,x 用函数值并开启 invalidateOnRefresh。

是什么

滚动触发(ScrollTrigger)是 GSAP 的滚动插件,包含在公开的 gsap npm 包中,免费使用,从 gsap/ScrollTrigger 导入并注册即可。它有两种典型用法:一是元素滚动到某个位置时触发一段动画;二是开启 scrub,让动画进度与滚动进度一一对应,向下滚动前进、向上滚动倒放。

上方演示属于第二种。在框内向下滚动时,方块向右移动、旋转并逐渐变圆,下方进度条同步显示当前进度;往回滚动,动画随之倒放。scrub: 0.6 表示动画用 0.6 秒追上滚动位置,手感更平滑。

核心参数

参数 含义
trigger 用来计算位置的元素
start / end 格式为「元素位置 视口位置」,如 'top 80%':元素顶部到达视口 80% 高度处
scrub true 直接绑定滚动;数字表示追赶的平滑秒数
pin 在 start 与 end 之间固定元素
toggleActions 进入、离开、回滚进入、回滚离开时的动作,默认 'play none none none'
markers 显示起止标记,仅用于调试
scroller 自定义滚动容器,默认是视口

代码示例

import { gsap } from 'gsap';
import { ScrollTrigger } from 'gsap/ScrollTrigger';

gsap.registerPlugin(ScrollTrigger);

const area = document.querySelector('.area');
const box = document.querySelector('.box');

gsap.to(box, {
  x: () => area.clientWidth - box.offsetWidth,
  rotation: 360,
  borderRadius: '50%',
  ease: 'none',
  scrollTrigger: {
    trigger: area,
    start: 'top 80%',
    end: 'bottom 20%',
    scrub: 0.6,
    invalidateOnRefresh: true, // 窗口尺寸变化时重新计算 x
    // markers: true,          // 调试时打开
    onUpdate: (self) => console.log(self.progress.toFixed(2)),
  },
});

什么时候用

  • 长页面的内容分段入场,让信息随阅读节奏出现。
  • 产品介绍、数据叙事中需要「固定画面、滚动推进」的段落。
  • 进度条、视差背景等与滚动位置严格对应的效果。

常见误区

  • 给时间轴里的子补间分别加 scrollTrigger:应该加在整个时间轴上,否则各自计算、互相冲突。
  • scrub 动画使用强缓动:进度已由滚动决定,一般写 ease: 'none'
  • 图片或字体加载后布局变化,却没有刷新:必要时调用 ScrollTrigger.refresh() 重新计算位置。
  • 上线时忘记删除 markers: true
esc