feat: integrate Motion One animation system (default-on)

- Add assets/motion.min.js (local fallback for offline demos)
- template.html: embed loader with local + CDN fallback chain,
  5 recipes (cascade / hero / quote / directional / pipeline)
- layouts.md: add data-anim markers to all 10 layouts,
  data-animate on pipeline / quote / directional layouts,
  Pre-flight section E documenting recipe decision tree
- components.md: add Motion 动效系统 chapter with loader,
  data attributes, recipes table, decision tree, FAQ
- checklist.md: add P1 entries 9b/9c and a 动效 self-check block
- SKILL.md: document animations in features list,
  resource tree, and loading order hints

Pipeline pages use manual advance: → / space / wheel-down light
up steps one by one; final → advances to next slide.
This commit is contained in:
郭浩 committed 2026-04-26 11:47:24 +08:00
1 parent a593cf4b73
commit e09f931308
6 files changed
+337 -69

No files matched your search

+70
View File
@@ -17,6 +17,7 @@
- [Icons 图标](#icons-图标)
- [Ghost 巨型背景字](#ghost-巨型背景字)
- [Highlight 荧光标记](#highlight-荧光标记)
- [Motion 动效系统](#motion-动效系统)
---
@@ -361,3 +362,72 @@
在文字底部生成一条半透明高亮条。深色主题用亮条,浅色主题用暗条(CSS 已处理)。
**适合场景**:只对关键 1-3 个词使用,不要大面积用。
---
## Motion 动效系统
整套 deck 默认开启翻页入场动画,由 Motion One(vanilla 版 Framer Motion,约 4KB)驱动。
### 加载方式
`assets/template.html` 底部的 module script 会先尝试**本地** `assets/motion.min.js`,失败则回落到 **jsdelivr CDN**,两者都失败则强制把所有带 `data-anim` 的元素设为 `opacity:1`—— 内容永远可读,演示不依赖网络。
```js
// template 里的核心加载器(不用改)
let motion;
try { motion = await import('./assets/motion.min.js'); }
catch(e1) {
try { motion = await import('https://cdn.jsdelivr.net/npm/motion@11.11.17/+esm'); }
catch(e2) {
document.querySelectorAll('[data-anim]').forEach(el=>{el.style.opacity='1';el.style.transform='none'});
}
}
```
### 数据属性驱动
你只需要在 HTML 里加两种属性:
```html
<!-- 1. 在 section 上选 recipe(可选,默认 cascade / hero 自动) -->
<section class="slide light" data-animate="quote">
<!-- 2. 在需要入场的元素上加 data-anim(可选值:left/right/line/step/divider) -->
<h1 class="h-xl" data-anim>大标题</h1>
<div class="stat-card" data-anim>...</div>
<div data-anim="left">左列内容</div>
<span data-anim="line" style="display:block">引用第一行</span>
```
### 5 种 recipe 一览
| recipe | 触发方式 | 行为 | 代表布局 |
|---|---|---|---|
| `cascade`(默认) | 不加 `data-animate` 即为此值 | 所有 `data-anim` 逐个 stagger 淡入,75ms/step | Layout 3 / 4 / 5 / 10 |
| `hero` | `.hero` slide 自动用此值 | 慢节奏 stagger,仪式感更强,160ms/step | Layout 1 / 2 / 7 |
| `quote` | `data-animate="quote"` | 其他元素先出,`data-anim="line"` 的行 550ms 间隔逐句揭示 | Layout 8 |
| `directional` | `data-animate="directional"` | `data-anim="left"` 从左滑入 → divider → `data-anim="right"` 从右滑入 | Layout 9 |
| `pipeline` | `data-animate="pipeline"` | 翻到此页 step 保持 15% 透明;按 →/空格/滚轮逐个点亮,最后一步才放行翻页 | Layout 6 |
### 给 slide 选 recipe 的决策树
1. **它是 `.hero` slide 吗?** → 不用加 `data-animate`,自动用 `hero`
2. **它是大引用金句页?** → `data-animate="quote"`,每句用 `<span data-anim="line" style="display:block">`
3. **它是左右对比 Before/After?** → `data-animate="directional"`,左列 `data-anim="left"`、右列 `data-anim="right"`
4. **它是流水线分步讲解?** → `data-animate="pipeline"`,每步 `data-anim="step"`
5. **其他所有正文页** → 什么也不加,自动用 `cascade`
### 什么元素该加 `data-anim`?
- ✅ 每一层有独立语义的块:kicker / h1 / h-xl / lead / callout / stat-card / figure / tag / rowline
- ✅ 多列结构里每一列,让它们逐列淡入而不是一起
- ❌ 不要在容器(`.grid-6` / `.frame`)上加,只加给叶子元素
- ❌ 不要在每个 `<li>` 上加,一般在 `<ul>` 层加就够
- ❌ 如果某页不想要任何动画(比如过渡页),整页不加 `data-anim` 即可 — Motion One 只对带标记的元素生效
### 常见问题
- **图片闪一下再出现?** 这是预期行为,翻页中段(450ms 时)触发动画
- **Pipeline 页卡住翻不下页?** 正确的,按 → 一步一步点亮 step,全部点亮后再按 → 才翻页
- **内容静态时也不显示?** 检查 motion.min.js 是否在 `assets/` 下;或者浏览器控制台看错误信息