# GSAP 保姆级教程

GSAP 是一个专业 Web 动画库，适合做页面入场动画、交互动效、滚动触发动画、SVG 动画和复杂时间线动画。

## 1. 最小可运行模板

把下面代码保存成 `gsap-demo.html`，双击或放到静态服务器里打开。

```html
<!doctype html>
<html lang="zh-CN">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>GSAP Demo</title>
  <style>
    body {
      display: grid;
      place-items: center;
      min-height: 100vh;
      margin: 0;
      background: #101218;
    }

    .box {
      display: grid;
      place-items: center;
      width: 120px;
      height: 120px;
      border-radius: 24px;
      background: #a8ff35;
      color: #111;
      font: 800 20px/1 Arial, sans-serif;
    }
  </style>
</head>
<body>
  <div class="box">GSAP</div>

  <script src="https://cdn.jsdelivr.net/npm/gsap@3.13.0/dist/gsap.min.js"></script>
  <script>
    gsap.to(".box", {
      x: 180,
      rotation: 360,
      duration: 1,
      ease: "power2.out"
    });
  </script>
</body>
</html>
```

## 2. 你必须先理解的 3 个方法

### `gsap.to()`

从当前状态动画到目标状态。

```js
gsap.to(".box", {
  x: 200,
  opacity: 0.5,
  duration: 1
});
```

适合：按钮 hover、卡片移动、元素淡出。

### `gsap.from()`

从某个起始状态动画到当前 CSS 状态。

```js
gsap.from(".title", {
  y: 40,
  opacity: 0,
  duration: 0.8
});
```

适合：页面加载入场动画。

### `gsap.fromTo()`

明确指定起始状态和结束状态。

```js
gsap.fromTo(".box",
  { x: 0, opacity: 0 },
  { x: 180, opacity: 1, duration: 1 }
);
```

适合：你不想依赖当前 CSS 状态时。

## 3. 常用属性

```js
gsap.to(".box", {
  x: 100,              // 横向移动
  y: 60,               // 纵向移动
  scale: 1.2,          // 缩放
  rotation: 180,       // 旋转
  opacity: 0.5,        // 透明度
  duration: 1,         // 持续时间，秒
  delay: 0.3,          // 延迟
  ease: "power2.out"   // 缓动
});
```

## 4. 多个元素错峰动画

HTML：

```html
<div class="item">A</div>
<div class="item">B</div>
<div class="item">C</div>
```

JS：

```js
gsap.from(".item", {
  y: 30,
  opacity: 0,
  duration: 0.6,
  stagger: 0.12
});
```

`stagger: 0.12` 的意思是每个元素相隔 `0.12s` 开始。

## 5. 时间线 Timeline

当动画超过两三步时，不要写一堆 `delay`，用时间线。

```js
const tl = gsap.timeline({
  defaults: {
    duration: 0.7,
    ease: "power3.out"
  }
});

tl.from(".hero", { opacity: 0, scale: 0.96 })
  .from(".title", { y: 40, opacity: 0 })
  .from(".desc", { y: 20, opacity: 0 }, "-=0.3")
  .from(".button", { y: 16, opacity: 0 }, "-=0.2");
```

`"-=0.3"` 表示比上一个动画结束提前 `0.3s` 开始。

## 6. 循环动画

```js
gsap.to(".dot", {
  y: -20,
  duration: 0.4,
  repeat: -1,
  yoyo: true,
  stagger: 0.1
});
```

- `repeat: -1`：无限循环
- `yoyo: true`：来回播放

## 7. ScrollTrigger 滚动触发

先引入插件：

```html
<script src="https://cdn.jsdelivr.net/npm/gsap@3.13.0/dist/gsap.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/gsap@3.13.0/dist/ScrollTrigger.min.js"></script>
```

再注册插件：

```js
gsap.registerPlugin(ScrollTrigger);
```

基础写法：

```js
gsap.from(".section-card", {
  scrollTrigger: {
    trigger: ".section-card",
    start: "top 75%",
    toggleActions: "play none none reverse"
  },
  y: 80,
  opacity: 0,
  duration: 0.8
});
```

关键点：

- `trigger`：谁进入视口时触发
- `start: "top 75%"`：元素顶部到达屏幕 75% 位置时触发
- `toggleActions`：进入、离开、返回时怎么播放

## 8. 常见问题排查

### 元素不动

检查选择器是否正确：

```js
console.log(document.querySelector(".box"));
```

如果输出 `null`，说明 `.box` 没找到。

### 控制台提示 `gsap is not defined`

说明你的动画代码写在 GSAP CDN 前面了。顺序必须是：

```html
<script src="gsap.min.js"></script>
<script>
  gsap.to(".box", { x: 100 });
</script>
```

### 动画看不到

检查元素有没有尺寸、背景、位置。

### ScrollTrigger 不生效

检查是否引入并注册：

```js
gsap.registerPlugin(ScrollTrigger);
```

## 9. 推荐学习路线

1. 先学 `gsap.to()`
2. 再学 `gsap.from()`
3. 学 `stagger`
4. 学 `timeline`
5. 最后学 `ScrollTrigger`

不要一开始就做复杂视差动画。先把一个按钮、一个标题、一组卡片动舒服。

