Communitygithub.com

KILN-skills/scroll-animation

使用 GSAP、ScrollTrigger、SplitText 和 Lenis 平滑滚动构建滚动驱动动画,包括揭示、固定区域、水平滚动、视差、擦洗时间线和文字效果,支持纯 JS、React、Next.js、Vue/Nuxt 或 Astro,并提供正确的设置、清理和响应式回退方案。

scroll-animation 是什么?

该技能专门用于构建基于滚动的 Web 动画,集成了 GSAP、ScrollTrigger、SplitText 和 Lenis 平滑滚动库。它提供了从安装、统一设置模块到各前端框架(React/Next.js、Vue/Nuxt、Astro、纯 JS)的完整集成指南,并特别强调了 ScrollTrigger 的正确使用规则以避免常见错误(如嵌套时间线、固定父容器、响应式处理等)。技能还涵盖了性能优化(优先使用 transform 和 opacity)、响应式设计(通过 gsap.matchMedia 适配不同屏幕和用户偏好)以及全面的验证方法。文档中包含具体的代码示例和最佳实践,帮助开发者快速创建流畅且健壮的滚动动画。

兼容平台~Claude Code~Codex CLI~Cursor
npx skills add https://github.com/KILN-skills/kiln/tree/HEAD/skills/scroll-animation

在你喜欢的 AI 中提问

打开一个已预加载此 Agent Skill 的新对话。

文档

Scroll Animation (GSAP + ScrollTrigger + Lenis)

如果已安装 GreenSock 的官方技能(gsap-core、gsap-scrolltrigger、gsap-react、gsap-plugins),请使用它们获取 API 详情;本技能涵盖项目设置、集成以及导致实际站点出错的常见错误。

1. 安装

npm i gsap lenis
npm i @gsap/react   # React / Next.js 专用

所有 GSAP 插件(ScrollTrigger、SplitText、Flip、ScrollSmoother、MorphSVG、DrawSVG…)都包含在公共 gsap 包中,并且可以免费用于商业项目。从 gsap/<PluginName> 导入并调用 gsap.registerPlugin(...) 一次即可。

2. 单一设置模块

创建 lib/motion/setup.(js|ts)(或 animations/),在客户端仅导入一次:

import gsap from "gsap";
import { ScrollTrigger } from "gsap/ScrollTrigger";
import { SplitText } from "gsap/SplitText";
import Lenis from "lenis";
import "lenis/dist/lenis.css";

gsap.registerPlugin(ScrollTrigger, SplitText);

export function initSmoothScroll() {
  if (matchMedia("(prefers-reduced-motion: reduce)").matches) return null;
  const lenis = new Lenis();
  lenis.on("scroll", ScrollTrigger.update);
  const tick = (time) => lenis.raf(time * 1000); // GSAP 时间单位为秒,Lenis 需要毫秒
  gsap.ticker.add(tick);
  gsap.ticker.lagSmoothing(0);
  return () => { gsap.ticker.remove(tick); lenis.destroy(); };
}

请仅使用 Lenis 或 GSAP ScrollSmoother,不要同时使用。

3. 框架集成

React / Next.js(App Router) — 使用 GSAP 的文件需要添加 "use client"。始终使用 useGSAP(自动清理,严格模式下不会重复执行):

"use client";
import { useRef } from "react";
import gsap from "gsap";
import { useGSAP } from "@gsap/react";
import { ScrollTrigger } from "gsap/ScrollTrigger";
gsap.registerPlugin(useGSAP, ScrollTrigger);

export function Features() {
  const root = useRef<HTMLElement>(null);
  useGSAP(() => {
    const mm = gsap.matchMedia();
    mm.add("(prefers-reduced-motion: no-preference)", () => {
      gsap.from(".feature", {
        autoAlpha: 0, y: 32, stagger: 0.08, ease: "power3.out",
        scrollTrigger: { trigger: root.current, start: "top 75%" },
      });
    });
  }, { scope: root }); // 选择器限定在该组件范围内
  return <section ref={root}>…</section>;
}
  • 创建动画的事件处理函数:使用 useGSAP 中的 contextSafe 包裹。
  • 平滑滚动提供者:在根布局中创建一个客户端组件,在 effect 中调用 initSmoothScroll()(或使用 lenis/react 中的 ReactLenis,设置 autoRaf: false 并结合 GSAP ticker)。
  • Next.js 中的路由变化:滚动到顶部(lenis.scrollTo(0, { immediate: true })),并在新页面挂载后调用 ScrollTrigger.refresh()。

Vue / Nuxt — 在 onMounted 中使用 gsap.context(() => {…}, rootEl) 创建,在 onUnmounted 中调用 ctx.revert()。Nuxt:使用客户端专属插件(plugins/gsap.client.ts)。

Astro / 静态多页面 — 在布局中使用 <script> 标签;配合 View Transitions 时,在 astro:page-load 事件中重新初始化,在 astro:before-swap 事件中销毁触发器。

纯 JS — 创建一个在 DOM 就绪后执行的 main.js;使用 gsap.context() 按区域分组。

4. ScrollTrigger 规则(可避免 90% 的 Bug)

  • 将 scrollTrigger 放在时间线或顶级 tween 上—切勿放在嵌套在时间线内的 tween 上。
  • 使用 scrub 时请同时使用 ease: "none"。
  • 创建顺序很重要:按页面从上到下的顺序创建触发器(或设置 refreshPriority),特别是使用固定(pin)功能时。
  • 固定一个容器,而不是你动画化的元素。不要在具有 transform 属性的父元素内部固定。除非有特殊意图,否则避免使用 pinSpacing: false。
  • 对于依赖视口大小的属性,使用函数值(x: () => …)并加上 invalidateOnRefresh: true。
  • 在图片、字体或动态内容改变布局后,调用 ScrollTrigger.refresh()(window.addEventListener("load", …),document.fonts.ready)。
  • 使用 markers: true 进行调试—上线前请移除。
  • 初始隐藏状态:使用 gsap.from/fromTo 或通过 JS 设置 autoAlpha,这样即使没有 JS 内容也是可见的。
  • 对于不应重复播放的揭示效果,使用 once: true(大多数情况都适用)。

5. 响应式与减少动画偏好

在每个场景外包裹 gsap.matchMedia():

const mm = gsap.matchMedia();
mm.add({
  isDesktop: "(min-width: 1024px)",
  isMobile: "(max-width: 1023px)",
  motionOK: "(prefers-reduced-motion: no-preference)",
}, ({ conditions: c }) => {
  if (!c.motionOK) return;            // 静态布局,无动画
  if (c.isDesktop) { /* 固定 / 水平滚动场景 */ }
  if (c.isMobile)  { /* 仅简单淡入上移效果 */ }
});

matchMedia 在条件变化时自动恢复—无需手动清理。

6. 性能

  • 动画化 x/y/scale/rotation/autoAlpha(变换和透明度)。避免动画化 width/height/top/left 以及在大面积上使用高消耗的 filter: blur()。
  • 优先为每个区域使用一个时间线,而不是使用数十个独立的触发器;对于大量相同的揭示效果,使用 ScrollTrigger.batch。
  • 使用 gsap.quickTo 实现指针跟随效果。
  • 在擦洗场景中的大图:使用合适的 sizes 属性,并避免每帧缩放巨大的位图。

7. 验证

快速上下滚动整个页面;调整窗口大小;在页面中间重新加载;导航离开后再返回(SPA)— 无跳跃、无重复固定区域、无控制台错误。在启用减少动画偏好、375px 宽度以及开启 CPU 节流的情况下进行测试。

常见效果配方:../motion-direction/references/patterns.md。

相关技能