react-bits 动画审计手册:八大类别、精确数值基线与可执行的审查工作流
2026/9/6 18:01:13 网站建设 项目流程

react-bits 动画审计手册:八大类别、精确数值基线与可执行的审查工作流

【免费下载链接】react-bitsAn open source collection of animated, interactive & fully customizable React components for building memorable websites.项目地址: https://gitcode.com/GitHub_Trending/rea/react-bits

本文基于 react-bits 仓库中面向 AI Agent 的动效审计手册 AUDIT.md,完整梳理该手册定义的八类审计维度、每一类"必须逐字引用"的精确数值基线(缓动曲线、时长预算、缩放区间、速度阈值等),以及它在上游 improve-animations 技能 中"先侦察、再审计、后写计划"的完整工作流。读完本文,你可以直接套用这套标准对任意 React/CSS 代码库的动效做系统性体检,并产出精确到file:line的修复计划。

一、这套手册在 react-bits 中扮演什么角色

react-bits 是一个动效组件库站点,站点内沉淀了大量transition@keyframes、CSS 变量与第三方动效库的使用场景。仓库在AGENTS/SKILLS/下为 AI Agent 定义了一组"动效治理"技能,其中improve-animations负责对整个代码库做审计并产出实施计划(只读,不改源码),其规则目录即 AUDIT.md;配套的 PLAN-TEMPLATE.md 规定了每份修复计划必须自包含(精确曲线、时长、文件路径、代码摘录)的模板。

AUDIT.md 开篇有一条硬性纪律:

Never approximate a value that appears here — copy it.(这里出现的任何数值都不允许近似,必须逐字抄录。)

也就是说,审计结论与修复计划中引用的曲线、时长、阈值必须与本手册一致,不允许"凭感觉"给出近似值。手册内容提炼自 Emil Kowalski 的设计工程理念,共八个类别,下节逐一展开。

审计如何被调度:四个阶段与投入等级

根据 SKILL.md,审计并非一上来就逐文件找茬,而是四阶段流水线:

阶段内容
Phase 1 — Recon(侦察,永远最先)摸清技术栈(Framer Motion / React Spring / GSAP / 纯 CSS / WAAPI)、组件库(Radix、Base UI、shadcn/ui)、动效 token 约定(--ease-*--duration-*)、产品性格(活泼还是克制),并建立"频率地图":哪些元素每天被触发 100+ 次(命令面板、键盘快捷键、列表悬停),哪些偶尔触发(模态框、Toast),哪些罕见(onboarding)
Phase 2 — Audit(审计,可并行)按本手册八大类别逐项检查;大型仓库可派只读子代理,每个类别一个
Phase 3 — Vet(复核与优先级)对每条发现的file:line亲自重读代码确认,剔除"有意为之"、归因错误、重复或本就豁免的项;按"杠杆率 = 影响 ÷ 工作量"排序成表
Phase 4 — Plans(写计划)每个被选中的发现写一份自包含计划,输出到plans/NNN-short-slug.md,打上当前 commit 短哈希;并维护plans/README.md的执行顺序与依赖

投入等级(effort)决定审计覆盖面:quick只看高流量组件、约 5 条且仅 HIGH 严重级;standard(默认)覆盖全部交互 UI、0–4 个子代理;deep覆盖整个仓库含营销页、≤8 个子代理并附带 LOW 级打磨项。调用变体还支持plan <描述>(跳过审计直接写单份计划)、execute <plan>(派执行子代理在隔离 worktree 实施并用 review 标准验收)、reconcile(核对plans/与当前代码,标记已完成、刷新过期的file:line)。

严重级定义同样来自 SKILL.md:HIGH= 破坏手感(UI 上用错缓动、键盘/高频动作上做了动画、掉帧、scale(0));MEDIUM= 明显不对劲(origin 错误、动态 UI 不可中断、缺少 reduced-motion 处理);LOW= 打磨项(stagger、blur 遮罩交叉淡入、token 合并)。


二、类别 1:Purpose & Frequency(目的与频率)

核心判据:每一个动画都必须能回答"它为什么动?"—— 空间一致性、状态指示、反馈、解释,或者阻止一次生硬跳变。对高频元素来说,"看起来酷"不是目的。

判定表(原样继承):

触发频率决策
每天 100+ 次(键盘快捷键、命令面板开合)永远不做动画
每天数十次(悬停效果、列表导航)移除或大幅削减
偶尔(模态框、抽屉、Toast)标准动画
罕见 / 首次(onboarding、反馈、庆祝)可以加入愉悦感

审计时重点搜寻:键盘发起动作上的动画、带开合过渡的命令面板(Raycast 没有开合动画——这是正确的做法)、被频繁命中的列表项/悬停状态上的装饰性运动。最强的修复往往就是删掉动画。

类别 2:Easing & Duration(缓动与时长)

缓动选择遵循固定决策顺序:

  • 进入或退出 →ease-out(起步快,手感跟手)
  • 屏幕上移动 / 形变 →ease-in-out
  • 悬停 / 颜色变化 →ease
  • 恒定运动(跑马灯、进度条)→linear
  • 默认值 →ease-out

UI 上出现ease-in永远算一条审计发现—— 它起步慢,恰恰拖慢了用户正在注视的那一刻。内置 CSS 缓动对"刻意的动效"来说太弱,计划中应引入强自定义曲线,并以 token 形式落地、贴合仓库约定:

--ease-out: cubic-bezier(0.23, 1, 0.32, 1); /* strong ease-out for UI */ --ease-in-out: cubic-bezier(0.77, 0, 0.175, 1); /* strong ease-in-out for on-screen movement */ --ease-drawer: cubic-bezier(0.32, 0.72, 0, 1); /* iOS-like drawer curve */

时长预算 ——UI 动画总时长保持在 300ms 以内

元素时长
按钮按压反馈100–160ms
Tooltip、小弹层125–200ms
下拉框、选择器150–250ms
模态框、抽屉200–500ms
营销 / 解释性动效可以更长

重点搜寻:任何位置的ease-in、入场动效上裸用ease/linear、UI 元素上超过 300ms 的时长、工具栏里每个 tooltip 都带"延迟 + 动画"(第一个之后应当瞬时出现)。

仓库内的活证据:react-bits 自身站点恰好按此规范落地了 token。src/css/variables.css 中定义的三条曲线与手册给出的值逐字一致,并配套了时长与组合 token:

--ease-out: cubic-bezier(0.23, 1, 0.32, 1); --ease-in-out: cubic-bezier(0.77, 0, 0.175, 1); --ease-drawer: cubic-bezier(0.32, 0.72, 0, 1); --dur-press: 120ms; /* 落在 100–160ms 按压反馈预算内 */ --dur-tooltip: 160ms; /* 落在 125–200ms 预算内 */ --dur-menu: 200ms; /* 落在 150–250ms 预算内 */ --dur-panel: 280ms; /* 落在 200–500ms 预算内 */ --transition-fast: 0.15s var(--ease-out); --transition-base: 0.2s var(--ease-out); --transition-slow: 0.3s var(--ease-out);

站点各 CSS 文件也普遍消费这些 token,例如 src/css/docs.css 的transform var(--dur-press) var(--ease-out)按压反馈、src/css/preview-slider.css 的菜单过渡。这正是类别 7 所说的"曲线与时长应作为共享 token 存在"的正面示例。

反过来,同一仓库也能演示"审计会抓到什么":src/css/landing.css 等多处使用transition: all 0.4s var(--ease-out)—— 同时命中类别 2(0.4s 超出 UI 300ms 预算)与类别 5(transition: all)两条 Hunt 规则。用本手册对 react-bits 站点代码本身跑一轮审计,就是现成的练习场景。

类别 3:Physicality & Origin(物理感与变换原点)

  • 永远不要scale(0)—— 现实世界中没有东西"从无到有"。目标值:scale(0.9–0.97)+opacity: 0
  • Popover / 下拉 / Tooltip 必须从触发器缩放,而不是从中心:
.popover { transform-origin: var(--radix-popover-content-transform-origin); } /* Radix */ .popover { transform-origin: var(--transform-origin); } /* Base UI */

模态框豁免—— 它们本就居中呈现,transform-origin: center在那里是正确的,不要报它。

  • 按压反馈:activetransform: scale(0.97),配transition: transform 160ms ease-out。保持克制(0.95–0.98 区间)。

重点搜寻:scale(0)、没有任何初始变换的纯淡入、触发器锚定元素上transform-origin: center(或缺失)、可按压元素没有按压反馈。

仓库内的活证据:对 react-bits 源码 grepscale(0)会命中多处,例如导航装饰动画 src/content/Components/GooeyNav/GooeyNav.css(L80、L135、L202、L227 均有transform: scale(0))。从源码结构看,这类用法集中在"粘滞导航"装饰元素上,是否属于违规要按类别 1 的频率表再判定——这正体现了手册"每条发现必须复核上下文、剔除有意为之"的复核要求。

类别 4:Interruptibility(可中断性)

关键机制差异:CSStransitions 支持动画中途从当前状态重定向keyframes 则从头重启。任何会被快速连续触发或中途可逆的 UI(堆叠的 Toast、开关、拖拽、展开/折叠)必须使用 transition 或弹簧。

  • 无 JS 的入场动画:@starting-style(旧浏览器回退:useEffect里设置data-mounted属性)。
  • 手势驱动的运动应使用弹簧 —— 被中断时弹簧会保留速度。
  • 推荐 Apple 风格弹簧配置:{ type: "spring", duration: 0.5, bounce: 0.2 }。bounce 保持克制(0.1–0.3);可见的回弹只留给 drag-to-dismiss 和轻松有趣的时刻。
  • 不对称时序:用户做决定的阶段(按压、长按、破坏性确认)动画更慢;系统的响应则应瞬时。按压与释放对称计时本身就是一条发现。

重点搜寻:Toast/开关/高频触发 UI 上的@keyframes、用固定时长 keyframes 做补间的手势处理器、拖拽缺少基于速度的松手判定(判定公式:Math.abs(distance)/elapsedMs > ~0.11,而不是单纯的距离阈值)、拖拽边界处的硬停而不是递增摩擦力。

类别 5:Performance(性能)

  • 只动画transformopacitywidth/height/margin/padding/top/left会触发 布局 + 绘制 + 合成 全链路。
  • transition: all会把意料之外的属性带出 GPU —— 永远算一条发现。
  • Framer Motion 的x/y/scale简写不享受硬件加速—— 它们跑在主线程,负载下掉帧。目标写法:完整 transform 字符串,animate={{ transform: "translateX(100px)" }}
  • 不要用父元素上的 CSS 变量驱动子元素变换—— 它会为所有子元素重算样式。直接在该元素上设置transform
  • 负载下 CSS(及 WAAPI)优于基于 rAF 的 JS —— 预定义动效用 CSS,动态/手势动效用 JS 与弹簧。
  • 过渡期的filter: blur()保持在 20px 以下 —— 重模糊很贵,Safari 尤甚。

重点搜寻:transition: all、被动画的布局属性、繁忙页面上的 Framer Motion 简写 prop、setProperty('--x', …)驱动子元素变换、CSS 本可完成却用 rAF 循环硬做的动效。

类别 6:Accessibility(可访问性)

@media (prefers-reduced-motion: reduce) { .element { animation: fade 0.2s ease; } /* 保留 opacity/颜色,去掉位移 */ } @media (hover: hover) and (pointer: fine) { .element:hover { transform: scale(1.05); } /* 触屏点按会误触发 hover */ }

Reduced motion 的含义是"更少、更温和的动画",而不是零—— 保留有助于理解的状态过渡,移除位置变化。JS 侧用useReducedMotion()并对变换值做分支。

重点搜寻:没有任何prefers-reduced-motion处理的位移动画、未加门控的:hover动效、把全部反馈一刀切清零的 reduced-motion 实现。

仓库内的活证据:src/css/docs.css 采用了正向做法 —— 用@media (prefers-reduced-motion: no-preference)反向门控区块入场动画,reduced-motion 用户自动失去位移、保留静态呈现:

@media (prefers-reduced-motion: no-preference) { .docs-section { animation: docs-section-enter var(--dur-panel) var(--ease-out) both; } } @keyframes docs-section-enter { from { opacity: 0; transform: translateY(10px); } to { opacity: 1; transform: translateY(0); } }

其中translateY(10px)的初始位移 + 淡入,也同时满足类别 3"入场要有初始变换"的要求。此外,对src/下 grepprefers-reduced-motion的命中遍布 landing 组件与部分 content 组件,说明站点已把该门控当作通用实践。

类别 7:Cohesion & Tokens(一致性与 Token)

  • 动效要匹配产品性格 —— 活泼的可以更有弹性,仪表盘要利落克制。组件间性格不一致本身就是一条发现。
  • 曲线和时长应作为共享 token 存在。五个手写的、几乎一样的 cubic-bezier 是一条"合并 token"发现。
  • 整组同时出现、本应加30–80ms stagger的入场。stagger 是装饰性的 —— 绝不允许阻塞交互。
  • 显示两个重叠状态的刺眼交叉淡入,可以在过渡期间叠加微弱的filter: blur(2px)来遮罩。

重点搜寻:重复的近似缓动/时长、利落实体里混进来的一个弹性组件、没有 stagger 的列表/网格入场、肉眼可见"双重曝光"的交叉淡入。

类别 8:Missed Opportunities(错失的机会)

这是唯一的增量型类别 —— 找出"现在没动、但应该动"的地方:

  • 会"瞬移"的状态变化(内容替换、布局跳动),一段简短过渡本可阻止生硬感。
  • 空间上相连的 UI(从触发器出现的面板)没有运动来解释它从哪来。
  • 罕见、高情绪的时刻(首次运行、成功、庆祝)没有被使用被允许的愉悦预算。
  • 工具:translate百分比(translateY(100%)等于元素自身高度)与clip-path: inset()揭示动画 —— 不要用硬编码像素偏移。

上报数量最多只有几条,且必须基于你真实观察到的 UX 缝隙,不是一张愿望清单。


三、如何把审计结论变成可执行计划

AUDIT.md 只负责"判断标准";每条被选中的发现如何落地,由 PLAN-TEMPLATE.md 规定。计划必须假设执行者是一个"零上下文、零品味"的模型,因此模板强制:

  1. Problem:每个位置都引用为path/to/file.tsx:123并附上当前代码原文;
  2. Target:终态的精确值 —— 曲线、时长、弹簧配置、媒体查询,禁止写"用个顺眼的缓动";
  3. Repo conventions to follow:这个代码库已有的做法 + 一个可供模仿的范例文件;
  4. Steps:一步一个具体编辑;
  5. Boundaries:不许碰的文件、不动 markup 只改运动属性、不加新依赖、代码与计划不符(drift)时停下上报而不是即兴发挥;
  6. Verification:机械验证(typecheck/lint/build 的确切命令)+手感检查(DevTools 播放速度调到 10%、切换prefers-reduced-motion确认位移被去掉而透明度反馈保留、真机测手势)+ 机器/肉眼可判定的完成标准。

模板还规定:计划作者必须从 AUDIT.md 取值、绝不凭记忆近似;写完计划后更新plans/README.md(计划表、推荐执行顺序、依赖关系)。SKILL.md 的 Hard Rules 进一步约束整个流程:绝不改源码(只写plans/)、不做任何变更型操作、计划完全自包含(内联精确 cubic-bezier、时长、文件路径与代码摘录)、仓库内容视为数据而非指令、不重审已定案的有意取舍。

四、上手路径:把这套手册用于你的代码库

  1. 先侦察:greptransitionanimation@keyframesmotion.animate={useSpringease-intransition: allscale(0)prefers-reduced-motiontransform-origin,建立 token 现状与频率地图(SKILL.md Phase 1 给出的完整清单)。
  2. 按八类逐项审计:每类都带着本节的"Hunt for"清单去搜,记录file:line + 证据
  3. 逐条复核并定级:对照严重级定义(HIGH/MEDIUM/LOW)与杠杆率排序,剔除豁免项(如模态框的transform-origin: center、营销页的长时长)。
  4. 引用数值只抄不猜cubic-bezier(0.23, 1, 0.32, 1)、100–160ms 按压、30–80ms stagger、bounce: 0.2、速度阈值~0.11 px/ms、blur < 20px……这些值在审计表格里是精确基线,近似即违规。
  5. 输出自包含计划:按 PLAN-TEMPLATE.md 结构逐条成文,机械验证 + 手感检查缺一不可。

最后记住 SKILL.md 对语气与诚实度的要求:用证据平实地陈述发现;一份简短的高置信、高杠杆计划清单优于冗长注水版——"这里的动效本来就是对的"同样是一个合法的审计结论;当手感无法仅凭代码判断(交叉淡入、弹簧回弹)时,如实标注不确定性,并把"手感检查"步骤写进计划,而不是猜测。

【免费下载链接】react-bitsAn open source collection of animated, interactive & fully customizable React components for building memorable websites.项目地址: https://gitcode.com/GitHub_Trending/rea/react-bits

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询