framework
framework/gsap/timeline-organization.md
medium
gsap-timeline-organization
timeline 集中 animations/<feature>.ts — 组件只调用。Use when 写 TS 业务代码 / 评审涉及 `timeline-organization` 的 PR。
timelinegsap.timelineanimations/集中组件只调用
paths
frontend/src/animations/**/*.ts
GSAP · timeline 组织
规则
所有 timeline 集中在 src/animations/<feature>.ts,组件只 import 并调用,不在组件文件里写 gsap.timeline()。
目录约定
src/animations/
├── tokens.ts # D / E 时长 / ease 常量
├── home.ts # 主页相关
├── outline.ts # 大纲页
├── editor.ts # 编辑器
├── task-waiting.ts # 任务等待
├── present.ts # 演示模式
└── dashboard.ts # 控制台
单个 timeline 文件模板
// src/animations/home.ts
import gsap from "gsap";
import { D, E } from "./tokens";
type Selector = gsap.utils.Selector;
export function buildHeroIntroTimeline(s: Selector): gsap.core.Timeline {
const tl = gsap.timeline({ defaults: { duration: D.base, ease: E.out } });
tl.from(s(".hero-title"), { y: 30, opacity: 0 })
.from(s(".hero-sub"), { y: 20, opacity: 0 }, "-=0.1")
.from(s(".hero-cta"), { scale: 0.8, opacity: 0 }, "-=0.05");
return tl;
}
export function buildCardStaggerTimeline(s: Selector): gsap.core.Timeline {
return gsap.timeline().from(s(".rec-card"), {
y: 20,
opacity: 0,
duration: D.slow,
ease: E.out,
stagger: 0.05,
});
}
组件调用
// src/pages/HomePage.tsx
import { useGSAP } from "@gsap/react";
import gsap from "gsap";
import { buildHeroIntroTimeline, buildCardStaggerTimeline } from "@/animations/home";
function HomePage() {
const rootRef = useRef<HTMLDivElement>(null);
useGSAP(() => {
const s = gsap.utils.selector(rootRef);
const intro = buildHeroIntroTimeline(s);
const cards = buildCardStaggerTimeline(s);
intro.add(cards, "-=0.1");
}, { scope: rootRef });
return <div ref={rootRef}>...</div>;
}
为什么集中
- 复用:多个组件共用同一 timeline 风格(如卡片 stagger)
- 可测试:timeline 是纯函数,可单测
- 维护:调时长、ease 只改一处
- 可读:组件文件不被动画细节淹没
反例
// ❌ 组件里写复杂 timeline
function HeroSection() {
useGSAP(() => {
const tl = gsap.timeline();
tl.from(".title", { y: 30, opacity: 0, duration: 0.24, ease: "power2.out" })
.from(".sub", { y: 20, opacity: 0, duration: 0.24, ease: "power2.out" }, "-=0.1")
.from(".cta", { scale: 0.8, opacity: 0, duration: 0.24, ease: "power2.out" }, "-=0.05");
// 散落在组件内,难复用难维护
}, ...);
}
自检
- [ ] 组件文件里没有
gsap.timeline()? - [ ] timeline 都在
src/animations/? - [ ] 时长 / ease 用
D/E常量? - [ ] timeline 函数有返回值(便于组合)?