HH/.agents/skills/huashu-design/references/animation-best-practices.md
ismail c5f76b3855
Some checks are pending
Build and Push Docker Image / build (push) Waiting to run
updates
2026-05-11 14:45:30 +03:00

20 KiB
Raw Permalink Blame History

Animation Best Practices · 正向动画设计语法

基于 Anthropic 官方三支产品动画Claude Design / Claude Code Desktop / Claude for Word 的深度拆解,提炼出的"Anthropic 级"动画设计规则。

配套 animation-pitfalls.md(避坑清单)使用——本文件是「应该这样做」, pitfalls 是「不要这样做」,两者正交,都要读。

约束声明:本文件只收录运动逻辑和表达风格不引入任何品牌色具体色值。 色彩决策走 §1.a 核心资产协议(从品牌 spec 抽取)或「设计方向顾问」 20 种哲学各自的配色方案)。本 reference 讨论的是「怎么动」,不是「什么色」。


§0 · 你是谁 · 身份与品味

在读后面任何技术规则之前,先读这一节。规则是从身份涌现的—— 不是相反。

§0.1 身份锚点

你是一个研究过 Anthropic / Apple / Pentagram / Field.io 运动档案的 motion designer。

做动画时,你不是在调 CSS transition——你是在用数字元素模拟一个物理世界 让观众的潜意识相信「这是有重量、有惯性、会溢出的物体」。

你不做 PowerPoint 式动画。你不做「fade in fade out」动画。你做的动画让人相信屏幕 是一个可以伸手进去的空间

§0.2 核心信念3 条)

  1. 动画是物理学,不是动画曲线 linear 是数字,expoOut 是物体。你相信屏幕上的像素值得被当作"物体"对待。 每一条 easing 的选择,都是在回答「这个元素有多重?摩擦系数多大?」的物理问题。

  2. 时间分配比曲线形状更重要 Slow-Fast-Boom-Stop 是你的呼吸。均匀节奏的动画是技术演示,有节奏的动画是叙事。 在正确的时刻慢下来——比在错误的时刻用对 easing 更重要。

  3. 礼让观众,比炫技更难 关键结果前停 0.5 秒是技术,不是妥协。让人类大脑有反应时间,是动画师的最高素养。 AI 默认会做一个没有停顿的、信息密度满格的动画——那是新手。你要做的是克制。

§0.3 品味标准 · 什么是美

你对「好」和「great」的判断标准如下。每一条都有识别方法——当你看到一个候选动画时, 用这些问题判断它是否达标,而不是机械对照 14 条规则。

美的维度 识别方法(观众反应)
物理重量感 动画结束时,元素""得稳——不是""在那里。观众潜意识觉得"这有重量"
礼让观众 关键信息出现前有一个可感的 pause≥300ms——观众来得及"看见"再继续
留白 收尾是戛然而止 + hold不是 fade to black。最后一帧清晰、肯定、有决定感
克制 全片只有一处「120% 精致」,其余 80% 恰到好处——到处炫技是廉价的信号
手感 弧线(不是直线)、不规律(不是 setInterval 的机械节奏)、有呼吸感
敬意 展示 tweak 的过程、展示 bug 的修复——不藏工作、不给"魔法"。AI 是协作者不是魔术师

§0.4 自检 · 观众第一反应法

做完一支动画,观众看完第一反应是什么?——这是你唯一要优化的指标。

观众反应 评级 诊断
"看起来挺流畅的" good 合格但无特色,你在做 PowerPoint
"这个动画真顺" good+ 技术对了,但没惊艳
"这个东西看起来真的像从桌面上浮起来的" great 你触到了物理重量感
"这不像是 AI 做的" great+ 你触到了 Anthropic 的门槛
"我想截图发朋友圈" great++ 你做到了让观众主动传播

great 和 good 的区别,不在于技术正确度,在于品味判断。技术正确 + 品味对 = great。 技术正确 + 品味空 = good。技术错误 = 没入门。

§0.5 身份和规则的关系

下面 §1-§8 的技术规则,是这套身份在具体场景的执行手段——不是独立规则清单。

  • 遇到规则没覆盖的场景 → 回到 §0身份判断,不要瞎猜
  • 遇到规则之间有冲突 → 回到 §0品味标准判断哪条更重要
  • 想破一条规则 → 先回答:"这样做符合 §0.3 哪一条美?" 答得上就破,答不上就别破

好。继续读下去。


总览 · 动画是物理学的三层展开

大多数 AI 生成动画有廉价感的根源是——它们表现得像「数字」不是「物体」。 真实世界的物体有质量、有惯性、有弹性、会溢出。Anthropic 三支片子的「高级感」根源, 就在于给数字元素一套物理世界的运动规则

这套规则有 3 个层次:

  1. 叙事节奏层Slow-Fast-Boom-Stop 的时间分配
  2. 运动曲线层Expo Out / Overshoot / Spring拒绝 linear
  3. 表达语言层展示过程、鼠标弧线、Logo 形变收束

1. 叙事节奏 · Slow-Fast-Boom-Stop 5 段结构

Anthropic 三支片子无一例外遵循这个结构:

占比 节奏 作用
S1 触发 ~15% 给人类反应时间,建立真实感
S2 生成 ~15% 视觉惊艳点出现
S3 过程 ~40% 展示可控性/密度/细节
S4 爆发 ~20% Boom 镜头拉远/3D pop-out/多面板涌现
S5 落幅 ~10% 品牌 Logo + 戛然而止

具体时长映射15 秒动画为例): S1 触发 2s · S2 生成 2s · S3 过程 6s · S4 爆发 3s · S5 落幅 2s

禁止做的事

  • 均匀节奏(每秒信息密度一样)— 观众疲劳
  • 持续高密度 — 无峰值无记忆点
  • 渐弱收尾fade out 到透明)— 应该戛然而止

自检:用纸笔画 5 个 thumbnail每个代表一段的高潮画面。如果 5 张图差别不大, 说明节奏没做出来。


2. Easing 哲学 · 拒绝 linear拥抱物理

Anthropic 三支片子的所有动效都用带「阻尼感」的贝塞尔曲线。默认的 cubic easeOut 1-(1-t)³不够锐——起步不够快、停顿不够稳。

三个核心 Easinganimations.jsx 已内置)

// 1. Expo Out · 迅速启动缓慢刹车(最常用,默认主 easing
// 对应 CSS: cubic-bezier(0.16, 1, 0.3, 1)
Easing.expoOut(t) // = t === 1 ? 1 : 1 - Math.pow(2, -10 * t)

// 2. Overshoot · 带弹性的 toggle/按钮弹出
// 对应 CSS: cubic-bezier(0.34, 1.56, 0.64, 1)
Easing.overshoot(t)

// 3. Spring 物理 · 几何体归位、自然落位
Easing.spring(t)

用法映射

场景 用哪个 Easing
卡片 rise-in / 面板入场 / Terminal fade / focus overlay expoOut(主 easing最常用
Toggle 切换 / 按钮弹出 / 强调交互 overshoot
Preview 几何体归位 / 物理落位 / UI 元素抖弹 spring
持续运动(如鼠标轨迹插值) easeInOut(保留对称性)

反直觉洞察

大多数产品宣传片的动画太快太硬linear 让数字元素像机器,easeOut 是基础分, expoOut 才是「高级感」的技术根源——它给数字元素一种物理世界的重量感


3. 运动语言 · 8 条共性原则

3.1 底色不用纯黑纯白

Anthropic 三支片子没有一支用 #FFFFFF#000000 做主底色。带色温的中性色 (或暖或冷)有"纸张 / 画布 / 桌面"的物质感,削弱机器感。

具体色值决策走 §1.a 核心资产协议(从品牌 spec 抽取)或「设计方向顾问」 20 种哲学各自的底色方案)。本 reference 不给具体色值——那是品牌决策,不是运动规则。

3.2 Easing 绝不是 linear

见 §2。

3.3 Slow-Fast-Boom-Stop 叙事

见 §1。

3.4 展示「过程」而非「魔法结果」

  • Claude Design 展示 tweak 参数、拖滑块(不是一键生成完美结果)
  • Claude Code 展示代码报错 + AI 修复(不是一次成功)
  • Claude for Word 展示 Redline 红删绿增的修改过程(不是直接给最终稿)

共同潜台词:产品是协作者、结对工程师、资深编辑——不是一键魔术师。 这精准打击专业用户对「可控性」和「真实性」的痛点。

反 AI slopAI 默认会做「魔法一键成功」的动画(一键生成 → 完美结果), 这是通用公约数。反过来做——展示过程、展示 tweak、展示 bug 和修复—— 是品牌识别度的来源。

3.5 鼠标轨迹人工绘制(弧线 + Perlin Noise

真人鼠标运动不是直线,是「起步加速 → 弧线 → 减速修正 → 点击」。 AI 直接直线插值的鼠标轨迹有潜意识排斥感

// 二次贝塞尔曲线插值(起点 → 控制点 → 终点)
function bezierQuadratic(p0, p1, p2, t) {
  const x = (1-t)*(1-t)*p0[0] + 2*(1-t)*t*p1[0] + t*t*p2[0];
  const y = (1-t)*(1-t)*p0[1] + 2*(1-t)*t*p1[1] + t*t*p2[1];
  return [x, y];
}

// 路径:起点 → 偏离中点 → 终点(做弧线)
const path = [[100, 100], [targetX - 200, targetY + 80], [targetX, targetY]];

// 再叠加极小的 Perlin Noise±2px制造「手抖」
const jitterX = (simpleNoise(t * 10) - 0.5) * 4;
const jitterY = (simpleNoise(t * 10 + 100) - 0.5) * 4;

3.6 Logo「形变收束」(Morph)

Anthropic 三支片子的 Logo 出场都不是简单 fade-in,是前一个视觉元素形变而来

共同模式:倒数 1-2 秒做 Morph / Rotate / Converge让整个叙事在品牌点上「坍缩」。

低成本实现(不用真 morph 让前一个视觉元素「坍缩」成一个色块scale → 0.1,向中心 translate 色块再「膨胀」展开成 wordmark。过渡用 150ms 快切 + motion blur filter: blur(6px)0)。

<Sprite start={13} end={14}>
  {/* 坍缩:前一个元素 scale 0.1opacity 保持filter blur 增加 */}
  const scale = interpolate(t, [0, 0.5], [1, 0.1], Easing.expoOut);
  const blur = interpolate(t, [0, 0.5], [0, 6]);
</Sprite>
<Sprite start={13.5} end={15}>
  {/* 膨胀Logo 从色块中心 scale 0.1 → 1blur 6 → 0 */}
  const scale = interpolate(t, [0, 0.6], [0.1, 1], Easing.overshoot);
  const blur = interpolate(t, [0, 0.6], [6, 0]);
</Sprite>

3.7 衬线 + 无衬线双字体

  • 品牌 / 旁白:衬线(有「学术感 / 出版物感 / 品位」)
  • UI / 代码 / 数据:无衬线 + 等宽

单一字体都是不对的。衬线给「品位」,无衬线给「功能」。

具体字体选择走品牌 specbrand-spec.md 的 Display / Body / Mono 三栈)或设计方向 顾问的 20 种哲学。本 reference 不给具体字体——那是品牌决策

3.8 焦点切换 = 背景减弱 + 前景锐化 + Flash 引导

焦点切换不只是降低 opacity。完整配方是

// 非焦点元素的滤镜组合
tile.style.filter = `
  brightness(${1 - 0.5 * focusIntensity})
  saturate(${1 - 0.3 * focusIntensity})
  blur(${focusIntensity * 4}px)        // ← 关键:加 blur 才真的"退后"
`;
tile.style.opacity = 0.4 + 0.6 * (1 - focusIntensity);

// 焦点完成后在焦点位置做 150ms Flash highlight 引导视线回流
focusOverlay.animate([
  { background: 'rgba(255,255,255,0.3)' },
  { background: 'rgba(255,255,255,0)' }
], { duration: 150, easing: 'ease-out' });

为什么 blur 是必须的:只靠 opacity + brightness焦点外的元素还是「锐利」的 视觉上没有「退到后景」的效果。blur(4-8px) 让非焦点真的退一层景深。


4. 具体运动技巧(可直接抄的代码片段)

4.1 FLIP / Shared Element Transition

按钮「膨胀」成输入框,不是按钮消失 + 新面板出现。核心是同一个 DOM 元素在 两种状态间 transition不是两个元素 cross-fade。

// 用 Framer Motion layoutId
<motion.div layoutId="design-button">Design</motion.div>
// ↓ 点击后同 layoutId
<motion.div layoutId="design-button">
  <input placeholder="Describe your design..." />
</motion.div>

原生实现参考 https://aerotwist.com/blog/flip-your-animations/

4.2「呼吸式」展开width→height

面板展开不是同时拉 width 和 height,而是:

  • 前 40% 时间:只拉 width保持 height 小)
  • 后 60% 时间width 保持,撑 height

这模拟物理世界「先展开,再注水」的感觉。

const widthT = interpolate(t, [0, 0.4], [0, 1], Easing.expoOut);
const heightT = interpolate(t, [0.3, 1], [0, 1], Easing.expoOut);
style.width = `${widthT * targetW}px`;
style.height = `${heightT * targetH}px`;

4.3 Staggered Fade-up30ms stagger

表格行、卡片列、列表项入场时,每个元素延迟 30mstranslateY 从 10px 回到 0。

rows.forEach((row, i) => {
  const localT = Math.max(0, t - i * 0.03);  // 30ms stagger
  row.style.opacity = interpolate(localT, [0, 0.3], [0, 1], Easing.expoOut);
  row.style.transform = `translateY(${
    interpolate(localT, [0, 0.3], [10, 0], Easing.expoOut)
  }px)`;
});

4.4 非线性呼吸 · 关键结果前悬停 0.5s

机器执行快且连贯,但关键结果出现前悬停 0.5 秒,让观众大脑有反应时间。

// 典型场景AI 生成完 → 悬停 0.5s → 结果浮现
<Sprite start={8} end={8.5}>
  {/* 0.5s 停顿——什么也不动,让观众盯着加载状态 */}
  <LoadingState />
</Sprite>
<Sprite start={8.5} end={10}>
  <ResultAppear />
</Sprite>

反例AI 生成完立刻无缝切到结果——观众没反应时间,信息流失。

4.5 Chunk Reveal · 模拟 token 流式

AI 生成文字不要用 setInterval 单字符蹦出(像老电影字幕),要用 chunk reveal ——一次出现 2-5 个字符,间隔不规律,模拟真实 token 流式输出。

// 分 chunk 而不是分字符
const chunks = text.split(/(\s+|,\s*|\.\s*|;\s*)/);  // 按词 + 标点切
let i = 0;
function reveal() {
  if (i >= chunks.length) return;
  element.textContent += chunks[i++];
  const delay = 40 + Math.random() * 80;  // 不规律 40-120ms
  setTimeout(reveal, delay);
}
reveal();

4.6 Anticipation → Action → Follow-through

Disney 12 原则中的 3 条。Anthropic 用得很显式:

  • Anticipation(预备):动作开始前有小反向动作(按钮轻微缩小再弹出)
  • Action(动作):主要动作本身
  • Follow-through(跟随):动作结束后有余韵(卡片落位后轻微 bounce
// 卡片入场的完整三段
const anticip = interpolate(t, [0, 0.2], [1, 0.95], Easing.easeIn);     // 预备
const action  = interpolate(t, [0.2, 0.7], [0.95, 1.05], Easing.expoOut); // 主动
const settle  = interpolate(t, [0.7, 1], [1.05, 1], Easing.spring);       // 回弹
// 最终 scale = 三段乘积或分段应用

反例:只有 Action 没有 Anticipation + Follow-through 的动画像「PowerPoint 动画」。

4.7 3D Perspective + translateZ 分层

想要「倾斜 3D + 悬浮卡片」的气质,给容器加 perspective给单个元素不同的 translateZ

.stage-wrap {
  perspective: 2400px;
  perspective-origin: 50% 30%;  /* 视线略俯视 */
}
.card-grid {
  transform-style: preserve-3d;
  transform: rotateX(8deg) rotateY(-4deg);  /* 黄金比例 */
}
.card:nth-child(3n) { transform: translateZ(30px); }
.card:nth-child(5n) { transform: translateZ(-20px); }
.card:nth-child(7n) { transform: translateZ(60px); }

为什么 rotateX 8° / rotateY -4° 是黄金比例

  • 大于 10° → 元素扭曲感过强,看起来像「倒下」
  • 小于 5° → 像「错切」而不是「透视」
  • × -4° 的非对称比例模拟「镜头在桌面左上角俯视」的 natural angle

4.8 斜向 Pan · 同时动 XY

镜头运动不是纯上下或纯左右,而是同时动 XY 模拟斜向移动:

const panX = Math.sin(flowT * 0.22) * 40;
const panY = Math.sin(flowT * 0.35) * 30;
stage.style.transform = `
  translate(-50%, -50%)
  rotateX(8deg) rotateY(-4deg)
  translate3d(${panX}px, ${panY}px, 0)
`;

关键X 和 Y 的频率不同0.22 vs 0.35),避免 Lissajous 循环规则化。


5. 场景配方(三种叙事模板)

参考材料里三支视频对应三种产品性格。选一种最贴合你的产品,不要混搭。

配方 A · Apple Keynote 戏剧式Claude Design 类)

适合大版本发布、hero 动画、视觉惊艳优先 节奏Slow-Fast-Boom-Stop 强弧线 Easing:全程 expoOut + 少量 overshoot SFX 密度:高(~0.4/sSFX 音高调到 BGM 音阶 BGMIDM / 极简科技电子,冷静+精密 收束:镜头急拉远 → drop → Logo 形变 → 空灵单音 → 戛然而止

配方 B · 一镜到底工具式Claude Code 类)

适合:开发者工具、生产力 App、心流场景 节奏:持续稳定 flow没有明显峰值 Easingspring 物理 + expoOut SFX 密度0(纯靠 BGM 驱动剪辑节奏) BGMLo-fi Hip-hop / Boom-bap85-90 BPM 核心技巧:关键 UI 动作踩在 BGM kick/snare 瞬态上——「音乐律动即交互音效

配方 C · 办公效率叙事式Claude for Word 类)

适合:企业软件、文档/表格/日历类、专业感优先 节奏:多 scene 硬切 + Dolly In/Out Easingovershoottoggle+ expoOut(面板) SFX 密度:中(~0.3/sUI click 为主 BGMJazzy Instrumental小调BPM 90-95 核心亮点:某一幕必有「全片高光」—— 3D pop-out / 脱离平面浮起


6. 反例 · 这样做就是 AI slop

反 pattern 为什么错 正确做法
transition: all 0.3s ease ease 是 linear 的亲戚,所有元素同速 expoOut + 分元素 stagger
所有入场都 opacity 0→1 没有运动方向感 配合 translateY 10→0 + Anticipation
Logo 淡入 没有叙事收束感 Morph / Converge / 坍缩-展开
鼠标直线移动 潜意识机器感 贝塞尔弧线 + Perlin Noise
打字单字蹦出setInterval 像老电影字幕 Chunk Reveal随机间隔
关键结果无悬停 观众没反应时间 结果前 0.5s 悬停
焦点切换只改 opacity 非焦点元素还锐利 opacity + brightness + blur
纯黑底 / 纯白底 赛博感 / 反光疲劳 带色温的中性色(走品牌 spec
所有动画同样快 无节奏 Slow-Fast-Boom-Stop
Fade out 收尾 无决定感 戛然而止hold 最后一帧)

7. 自检清单(动画交付前 60 秒)

  • 叙事结构是 Slow-Fast-Boom-Stop不是均匀节奏
  • 默认 easing 是 expoOut,不是 easeOutlinear
  • Toggle / 按钮弹出用了 overshoot
  • 卡片 / 列表入场有 30ms stagger
  • 关键结果前有 0.5s 悬停?
  • 打字用 Chunk Reveal不是 setInterval 单字?
  • 焦点切换加了 blur不只是 opacity
  • Logo 是形变收束Morph不是淡入
  • 底色不是纯黑 / 纯白(带色温)?
  • 文字有衬线 + 无衬线层次?
  • 收尾是戛然而止,不是渐弱?
  • (有鼠标的话)鼠标轨迹是弧线,不是直线?
  • SFX 密度符合产品性格(见配方 A/B/C
  • BGM 和 SFX 有 6-8dB 响度差?(见 audio-design-rules.md

8. 与其他 reference 的关系

reference 定位 关系
animation-pitfalls.md 技术避坑16 条) 不要这样做」· 本文件的反面
animations.md Stage/Sprite 引擎用法 动画怎么写的基础
audio-design-rules.md 双轨制音频规则 动画配音频的规则
sfx-library.md 37 个 SFX 清单 音效素材库
apple-gallery-showcase.md Apple 画廊展示风格 一种特定运动风格的专题
本文件 正向运动设计语法 应该这样做

调用顺序

  1. 先看 SKILL.md 工作流程 Step 3 的位置四问(决定叙事角色和视觉温度)
  2. 选定方向后读本文件确定运动语言(配方 A/B/C
  3. 写代码时参考 animations.mdanimation-pitfalls.md
  4. 导出视频时走 audio-design-rules.md + sfx-library.md

附录 · 本文件素材来源

  • Anthropic 官方动画拆解:花叔项目目录的 参考动画/BEST-PRACTICES.md
  • Anthropic 音频拆解:同目录 AUDIO-BEST-PRACTICES.md
  • 3 支参考视频:ref-{1,2,3}.mp4 + 对应 gemini-ref-*.md / audio-ref-*.md
  • 严格过滤:本 reference 不收录任何具体品牌色值、字体名、产品名。 色彩/字体决策走 §1.a 核心资产协议或 20 种设计哲学。