Communitygithub.com

动效设计原则

动效的审美层:选择正确的缓动(ease-in / ease-out / ease-in-out / spring),把握时间与节奏,构建预期→动作→余韵的弧线,并应用迪士尼动画原则。

动效设计原则 是什么?

动效设计原则(Motion Design Principles)是一个专注于动效审美判断的专业技能,适用于AI代理工具,如Claude Code、Coder、Cursor等。它决定元素“如何”移动,以呈现精致、有意图的效果,而非廉价或卡顿。该技能的核心在于诊断动效问题(线性/漂浮/卡顿/死板),然后通过六步操作流程提供解决方案:命名问题、选择缓动曲线、调整时间与间距、构建预期→动作→余韵弧线、应用迪士尼动画原则(如慢入慢出、预备动作、跟随动作等),最后输出标准化的动效规格。它明确区分了动效判断与执行——该技能仅负责曲线、时间和弧线的决策,而将渲染或编排工作交由其他技能(如 product-demo-director 用于产品视频,或CSS/JS过渡用于UI)。技能文档提供了自包含的Node.js脚本(motion_pick.js),用于自动生成缓动曲线、时间、帧数和驱动方式(spring vs interpolate)的推荐值,支持30fps的产品视频场景。关键规则包括:入场使用ease-out,出场使用ease-in,界面上A→B移动使用ease-in-out,物理/生动效果使用spring,精确时间值(如透明度、颜色、进度条)使用interpolate,出场时间约为入场的0.7–0.8倍。

兼容平台~Claude Code~Codex CLI✓Cursor
npx skills add https://github.com/SkillMedev/tutorial-video-studio/tree/main/skills/motion-design-principles

在你喜欢的 AI 中提问

打开一个已预加载此 Agent Skill 的新对话。

文档

动效设计原则 是做什么的?

这是品味层。它决定如何移动,使得动效看起来精致、有意图,而不是卡顿、漂浮或廉价。它不编写执行动效的代码——一旦你决定了曲线、时间和弧线,该决策将成为输入,传递给编排/渲染技能(用于产品视频,传递给 product-demo-director;用于UI,传递给CSS/JS过渡)。请保持这两项工作分离:该技能拥有判断权;编排技能拥有组织和机制权。

触发于任何关于动效感觉的问题:“让它不那么卡顿”、“更流畅”、“更精致”、“更有生命力”、“缓动有问题”、“看起来很廉价”、“我该用ease-in还是ease-out”、“用spring还是插值”。

何时使用同级技能

该技能仅负责曲线/时间/弧线的判断。当真正的问题属于以下情况时,请移交给其他技能:

  • 镜头选择、场景顺序或节奏列表 → video-storyboard。
  • 编排完整的产品演示——光标移动、屏幕录制、功能标注、端到端场景组装 → product-demo-director。(该技能产生此技能消费的动效规格。)
  • 文字或字母动画——飞行/构建/揭示类型的文字 → kinetic-typography。
  • 将动效与节拍、配乐或音效同步 → sound-and-music-sync。
  • 为平台裁剪或重新构图(9:16, 1:1, 安全区域) → social-video-formatter。
  • 光线、曝光、辉光或色彩动效 → motion-color-and-light。

操作流程

先诊断,再开处方。大多数“卡顿”动效属于四种命名问题之一,每种问题都对应特定的修复方法。按顺序执行步骤——如果时间不对,缓动修正就毫无价值;如果元素没有弧线,时间修正也毫无价值。

步骤1:命名问题所在

观察动效(或对其的描述)并归类。几乎所有的抱怨都属于以下之一:

  • 线性/机械——匀速移动,然后突然停止。没有缓动。在步骤2中修复。
  • 漂浮/绵软——速度太慢,或者同时进行缓入和缓出,本该快入。时长或曲线错误。在步骤2和步骤3中修复。
  • 卡顿/抖动——进入和退出速度相同,或者所有属性在同一条平坦时间线上动画,没有偏移。缺少间距和弧线。在步骤3和步骤4中修复。
  • 死板/无生命力——技术上正确但无聊:没有预备动作,没有过冲,没有跟随动作。缺少弧线和二次运动。在步骤4和步骤5中修复。

在动手之前,用一行文字写下诊断结果。“模态框因为以ease-in-out在600ms内淡出而显得漂浮”是一个修复方向;“让它好看点”不是。

步骤2:选择缓动曲线

缓动是动效的速度-时间曲线形状。曲线几乎承载了所有感知质量。将曲线与元素的行为相匹配:

  • ease-out(快速开始,慢速结束)——元素进入以及用户触发的任何操作的默认值。它感觉响应迅速,因为动效立即开始,然后减速到位。用于:元素出现、下拉菜单打开、点击按钮响应、内容滑入。如果不确定,选择 ease-out。
  • ease-in(慢速开始,快速退出)——元素离开。元素加速移出屏幕。如果单独用于进入,会感觉迟钝和滞后,这是“漂浮”感的第一大原因。用于:关闭、退出。
  • ease-in-out(慢、快、慢)——将已在屏幕上的元素从A移到B:卡片重新排序、轮播前进、开关滑动。两端都锚定,因此两端缓动感觉可控。不要将其用于进入——慢速启动会破坏响应性。
  • spring(物理:质量、刚度、阻尼——过冲然后稳定)——用于动效应感觉有生命力和物理感:模态框弹出、开关旋钮、点赞按钮、通知落下。轻微的过冲正是“有生命力”的原因。调整阻尼以体现个性:较低的阻尼 = 更有弹性和俏皮,较高的阻尼 = 更紧凑和商务。

spring() vs interpolate() 的决策(在代码中何时使用哪一个)位于质量标准和下文可执行工件中。简而言之:spring用于物理/生动的变换,interpolate用于精确到帧的时间值,如透明度淡入淡出、颜色和进度条。

步骤3:设置时间和间距

时间是总时长。间距是距离在时间上的分布方式——间距就是字面意义上的缓动(ease-out意味着帧集中在末尾)。两条规则:

  • 时长与距离和尺寸成比例,而非审美。 小元素短距离移动应快速(UI:约150–250ms)。大元素或长距离需要更长的时间(约300–500ms),否则会像瞬移。视频中大的全屏/主要动效可以更长。同样的动效,距离越长→时长越长。
  • 进入和退出不对称。 退出应比进入更快(约0.7–0.8倍)——用户已经完成了与该元素的交互,所以让它快速离开。相等的进入/退出时长是“卡顿”的经典来源。

对于产品视频,一旦离开该技能,立即转换为帧数:frames = round(seconds * fps)。这些帧数是您传递给 product-demo-director(它会将这些帧数转换为定时场景计划)的字面输入。

步骤4:构建预期→动作→余韵的弧线

真实的运动很少是单一动作。最丰富、最有“生命力”的动效有三个节拍:

  1. 预期——在主要动作之前,一个微小的反向蓄力(按钮在弹出前向内轻按,卡片在滑出前向后拉)。它让眼睛做好准备,并使动作显得有意图。保持微小且快速;过多会看起来像故障。
  2. 动作——主要动作,承载了步骤2的缓动和步骤3的时长。这是间距所在。
  3. 余韵——元素超过目标然后返回(弹簧过冲),以及任何附加/次级元素稍微滞后于主导元素(标签追上它所位于的卡片)。这就是重量感和生命感的来源。

并非每个微交互都需要三者——一个150ms的工具提示只有动作。但当某些东西感觉“死板”时,几乎总是缺少预期或余韵。在添加装饰之前先添加弧线。

步骤5:应用相关的迪士尼原则

迪士尼的12条动画原则可以直接映射到UI和产品动效上。不需要全部应用;只需使用解决诊断问题的少数几个。完整映射在 references/twelve-principles 中。高杠杆率的原则:

  • 慢入慢出 → 缓动(步骤2)。单个最大的质量杠杆。
  • 预期 → 蓄力(步骤4)。
  • 余韵与重叠动作 → 过冲 + 滞后的次要元素(步骤4)。“正确”与“有生命力”之间的区别。
  • 时间 → 时长和间距(步骤3)。
  • 挤压与拉伸 → 在按压/碰撞时微妙的缩放以暗示质量;在UI中保持在几个百分点以内,否则会看起来像玩具。
  • 表演 → 一次只移动一个东西,让眼睛知道看哪里;绝不同时在相同曲线上动画化六个东西。
  • 辅助动作 → 一个小的支持性动效(卡片抬起时阴影加深),强化主要动作而不与之竞争。
  • 夸张 → 将关键姿势略微推过现实;在UI中克制,在有力的产品视频中更自由。

步骤6:移交规格

填写下面的动效规格模板——曲线、时长(和帧数)、弧线节拍以及每个属性的spring-vs-interpolate选择。填写好的规格是交接工件:对于产品视频场景,它直接输入到 product-demo-director;对于UI,它成为您的过渡/关键帧值。如果场景还需要光线/曝光动效,请与 motion-color-and-light 配合使用;如果文字正在动画化,请与 kinetic-typography 配合使用;如果时间必须落在节拍上,请与 sound-and-music-sync 配合使用。

质量标准

动效只有满足以下所有条件才能达到A+:

  • 诊断已命名(线性/漂浮/卡顿/死板),并且每个更改都可追溯到此诊断。没有无理由的“让它好看点”。
  • 进入使用ease-out,退出使用ease-in,屏幕上A→B使用ease-in-out,生动/物理使用spring。 除非是故意的匀速循环(如加载旋转器、跑马灯),否则不允许原始线性动效。
  • 时长与距离/尺寸成比例,且退出快于进入。
  • spring() 与 interpolate() 的选择针对每个属性显式声明:物理变换用spring(缩放、平移、弹出/滑动/稳定——需要过冲);精确时间值用interpolate(透明度淡入淡出、颜色、进度,任何过冲看起来不对的地方)。由spring驱动的淡入淡出,或由线性interpolate驱动的标志弹出,都是缺陷。
  • 在主要/标志性动效上至少存在预期或余韵之一;无生命力的动效正是缺少这些。
  • 一次只主导一个东西(表演);属性应偏移而非全部在同一条平坦时间线上触发。
  • 曲线、时长和帧数已书面记录,并准备好移交给product-demo-director或过渡——该技能绝不将决策隐式化。

禁止事项

  • 不要为进入或退出使用线性缓动——这是机械的默认值,看起来未完成。匀速仅用于有意的循环。
  • 不要为进入使用ease-in,或为退出使用ease-out——这是相反方向上的漂浮/滞后感。进入使用ease-out,退出使用ease-in。
  • 不要使用相等的进入和退出时长;退出应快约0.7–0.8倍。
  • 不要用spring驱动淡入淡出、颜色或进度条——过冲会使值超出范围并闪烁。时间值请使用interpolate。
  • 不要在你希望动效感觉有生命力时,用线性interpolate驱动生动的弹出/滑动/缩放——使用spring来获得过冲。
  • 不要在同一条平坦时间线上动画化多个属性;应分阶段并偏移它们。
  • 不要在UI中过度预期或过度过冲——几个像素/几个百分点即可。大幅的蓄力和弹跳会看起来像故障或玩具。
  • 不要在此处规划镜头顺序或组装演示——将规格移交给product-demo-director;故事板顺序由video-storyboard负责。

缓动与spring选择器

自包含的Node脚本。保存为 motion_pick.js 并使用 node motion_pick.js 运行。编辑 requests 数组以包含您正在动画化的元素;它将返回曲线、按距离缩放的时长(毫秒和帧数)、退出时长以及spring-vs-interpolate选择。无依赖。

// 动效选择器。编辑 `requests`,然后:node motion_pick.js
const fps = 30 // 用于产品视频;UI忽略帧列

// role: 'enter' | 'exit' | 'move' | 'lively'
// distancePx: 移动距离(驱动时长)。sizePx: 元素大致尺寸。
const requests = [
  { name: 'Modal pop-in',    role: 'lively', property: 'scale',   distancePx: 0,   sizePx: 600 },
  { name: 'Modal backdrop',  role: 'enter',  property: 'opacity', distancePx: 0,   sizePx: 1920 },
  { name: 'Toast slide-in',  role: 'enter',  property: 'translate', distancePx: 320, sizePx: 360 },
  { name: 'Toast dismiss',   role: 'exit',   property: 'translate', distancePx: 320, sizePx: 360 },
  { name: 'Card reorder',    role: 'move',   property: 'translate', distancePx: 140, sizePx: 280 },
  { name: 'Progress fill',   role: 'move',   property: 'width',     distancePx: 800, sizePx: 800 },
]

function curveFor(role) {
  if (role === 'enter') return 'ease-out'
  if (role === 'exit') return 'ease-in'
  if (role === 'move') return 'ease-in-out'
  return 'spring' // lively
}

// 时长随移动距离和元素尺寸缩放。基线+斜率,带钳位。
function durationMs(role, distancePx, sizePx) {
  const reach = Math.max(distancePx, sizePx * 0.4)
  let ms = 140 + reach * 0.45
  ms = Math.min(Math.max(ms, 140), 600)
  if (role === 'exit') ms *= 0.75 // 退出更快
  return Math.round(ms)
}

// spring用于物理变换;interpolate用于时间值。
function driver(role, property) {
  const physical = property === 'scale' || property === 'translate'
  if (role === 'lively') return 'spring()  // 需要过冲'
  if (physical && role !== 'move') return 'spring()  // 物理,生动的稳定'
  return 'interpolate()  // 精确,同步到帧'
}

const pad = (s, n) => String(s).padEnd(n)
console.log(pad('ELEMENT', 18), pad('CURVE', 12), pad('MS', 6), pad('FRAMES', 8), 'DRIVER')
for (const r of requests) {
  const curve = curveFor(r.role)
  const ms = durationMs(r.role, r.distancePx, r.sizePx)
  const frames = Math.round((ms / 1000) * fps)
  console.log(pad(r.name, 18), pad(curve, 12), pad(ms, 6), pad(frames, 8), driver(r.role, r.property))
}

示例输出

使用上述请求,脚本打印:

ELEMENT            CURVE       MS     FRAMES   DRIVER
Modal pop-in       spring      252    8        spring()  // 需要过冲
Modal backdrop     ease-out    600    18       interpolate()  // 精确,同步到帧
Toast slide-in     ease-out    284    9        spring()  // 物理,生动的稳定
Toast dismiss      ease-in     213    6        interpolate()  // 精确,同步到帧
Card reorder       ease-in-out 203    6        interpolate()  // 精确,同步到帧
Progress fill      ease-in-out 500    15       interpolate()  // 精确,同步到帧

解读:模态框弹出使用spring(过冲=有生命力),而其背景仅淡入使用定时interpolate——同一组件上两种不同的驱动方式,完全符合质量标准的要求。Toast在284ms内进入,在213ms内更快地退出(0.75倍退出规则),其滑动是物理的,因此用spring进入但用interpolate退出。进度条是精确的宽度值——绝不使用spring,否则填充会抖动。

Individual skills in this repo

This repo contains 11 individual skills — each has its own dedicated page.

Captions From Transcript

Produce an accurate, properly timed caption track (SRT or WebVTT) from a video

Kinetic Typography

Put text in motion the right way - title cards, animated captions, lower-thirds, callouts, and word-by-word reveals - with a reading-time-per-word budget so copy holds long enough to read, plus enter/exit timing, weight and size transitions, and type hierarchy in motion. Use when someone asks to

Narration Script

Write the spoken voiceover for a tutorial or demo - the actual words, phrased for the ear and synced one-instruction-per-action to what is on screen, with a pacing budget and a confident, jargon-checked tone. Use when someone says

Product Demo Director

Direct the craft of putting a real software UI on screen - cursor choreography, zoom/pan/callout language, screen-recording vs recreated-UI, and making state changes legible with highlights, focus pulls, and slow-downs. Use when filming or recreating an app for a product demo, feature walkthrough, onboarding clip, or release reel and asking

Remotion Compose

Turns a natural-language video brief into a complete, ready-to-preview Remotion composition - extracts duration, scenes, brand colors, aspect ratio, and real copy; plans the frame budget; and writes data-driven React/TypeScript using useCurrentFrame, interpolate, spring, AbsoluteFill, and Sequence, registered in Root.tsx. Use when someone says

Remotion Render

Renders a Remotion composition to MP4 and runs the edit-and-re-render loop - CLI render commands, 1080p/4K/9:16 presets, concurrency tuning, codec selection, batch variants from a JSON data file, and Lambda for cloud rendering. Use when someone says

Remotion Setup

Scaffolds a new Remotion video project wired for Claude Code Agent Skills - Node check, create-video scaffold, skills install, folder conventions, Google Fonts, and a smoke-test render. Use whenever someone wants to start making videos with Remotion and Claude, even just

Screencast Capture

Capture clean raw screen and camera footage for a tutorial or product demo - choosing the recorder (macOS Screenshot toolbar, QuickTime, OBS, Windows Game Bar), setting resolution / frame-rate / cursor / microphone, prepping a distraction-free stage, and recording in retakeable segments. Use when someone says

SkillMedev/tutorial-video-studio

Plan a product demo, feature announcement, or launch video as a beat sheet and shot list BEFORE animating - hook in the first 3s, problem, reveal, proof, CTA - with target duration and pacing per scene type, output as a JSON scene plan that remotion-compose consumes directly. Use when someone says

Social Video Formatter

Reframe and export a finished video for social platforms - 9:16 ↔ 16:9 cropping, burned-in captions, a platform-native first frame, loop design, and per-platform specs (aspect, length, safe areas) for TikTok, Reels, Shorts, X, and LinkedIn. Use when someone says

Sound and Music Sync

Score a video like an editor: beat-match cuts to the music, land SFX on transitions, pace the voiceover so it breathes, source royalty-free tracks safely, and duck the music so the VO sits clearly on top. Use when adding music, sound effects, or voiceover to a video, when asked to

相关技能