何时读本文件:画面里出现任何「镜头级」运动之前——zoom / pan / orbit / parallax / 转场 / 定场谢幕,只要动的是「镜头」而不是「元素」,先读这里再写 timeline。 元素怎么动(入场/stagger/物理感)归
animation-best-practices.md; 本文件回答的是镜头什么时候动、动多大、动多久、镜头之间怎么接。 GSAP 侧的可运行实现(rig 容器、PageCam 翻译、对数时长 helper)见gsap-recipes.md的「Camera Rig 配方」节,本文只给设计判断和公式。参数出处标注约定:(HuaRec) = 花录 Studio 运镜导演系统实测参数; (shotcraft) = video-shotcraft 106 卡镜头体系;(实测) = 本 skill 项目实战; (推测) = 通用电影语汇借鉴,参数待实测校准。
大多数 AI 生成动画的运镜是「特效制」思维:哪里能加 zoom 就加 zoom,镜头动得越多越「高级」。 这是晕和廉价感的共同来源。正确的心智模型来自两条公理 (HuaRec):
| 预算项 | 典型值 | 调节手感 |
|---|---|---|
| 相邻镜头变化间隔 | ≥2.6-3.0s(克制档 5.0s) | 低于 2.6s 观众开始晕;MTV 式快剪不适用于产品演示 (HuaRec) |
| 任意 15s 窗口内镜头变化 | ≤4-5 次(克制档 3 次) | 超了就砍最弱动机的那一镜,不是压缩间隔 (HuaRec) |
| 推进倍率下限 | 1.25x | 低于 1.25x 的 zoom 视觉变化感知不足,纯属晃动,不拍(定场 1.06x 是唯一例外)(HuaRec) |
| 推进倍率上限 | 2.3x(克制档 1.8x) | 再高像素密度撑不住,先换素材再谈倍率 (HuaRec) |
| 每分钟镜头数 | 克制 ≤4 镜/分,常规 ≤6 镜/分 | 「留呼吸,不是 MTV」(HuaRec) |
再叠两条风格公理 (shotcraft):
这两条与 best-practices §0.2 的「礼让观众」同源:镜头是替观众的眼睛做决定, 决定做得越少、越准,观众越信任你。
每个镜头动作先问动机:这一镜替观众回答了什么问题? 答不上来就不动。
| 镜头 | 动机(什么时候给) | 参数区间 | 禁忌 |
|---|---|---|---|
| push in 推近 | 「接下来看这里」:聚焦一个具体 UI 元素 / 数据 / 关键词;紧张度爬升 | 倍率 1.3 / 1.45 / 1.8 / 2.3 档(见 §4);时长走对数公式;提前 0.15s 进镜 (HuaRec) | <1.25x 不推;滚动 / 切页 / 播视频等全屏级变化期间不推(「滚动时推近会晕」);旁白中段不动镜(见 §6 move on pause)(HuaRec) |
| pull out 拉远 | 揭示全貌与上下文:「原来它属于一个更大的系统」;收尾谢幕 | 时长同对数公式;谢幕拉出 0.55s + ≥0.8s 全景停顿 (HuaRec) | 禁「出-进-出」泵动:镜间空隙小于过渡时长时直接接下一镜,不回 1x(见 §5)(HuaRec) |
| pan 平移 | 两个中距焦点之间转移(归一化距离 0.22-0.45);一镜扫过多个并列元素 | 联合倍率 ≥1.25 才值得平移;斜向 pan 用双频正弦(X/Y 频率比 0.22:0.35,振幅 30-40px)(HuaRec / 本 skill 既有) | 焦点距离 >0.45 不平移(对角横跳),弃镜;纯单轴 pan 有机械感,优先斜向 |
| orbit 环绕 | 单主角质感特写,「实体感」最强的一镜;hero 元素立传 | rotY 主导 + persp 1100-1200px;实测机位 rotX46/rotY−30/rotZ9 → rotX42/rotY26/rotZ−7 (shotcraft) | 一种手法全片只当一次主角 (shotcraft);信息密集画面禁用(机位服务可读性,文字多就正视) |
| dolly zoom | 「世界观反转」的揭示瞬间:主体不变、语境剧变 | 伪配方见 §8:主体钉死,背景 scale 1→2.0-2.5 + opacity ≤0.6 (shotcraft) | 全片最多一次;无叙事落差时用它 = 纯炫技 |
| 静止 | 文字阅读、真人速度交互演示、信息密集镜头;预算不足时的默认答案 | 品牌字标落定 hold ≥1s;批量动效收尾 0.5s 静止;开场主体动作弧 ≥3s (shotcraft) | 无。静止不动永远是合法选择,「不给镜头」本身就是导演决定 |
两条横向规则:
「推近」有两种实现,观感完全不同,先选型再写代码:
| 维度 | zoom(scale 缩放) | dolly(perspective + translateZ 前移) |
|---|---|---|
| 视差 | 无。所有层等比放大,画面是「一张图被放大」 | 有。近层快、远层慢,画面是「镜头在空间里前进」 |
| 观感 | 干净、信息型,适合 UI 特写 / 数据聚焦 | 空间感、电影感,适合 hero 展示 / 氛围段落 |
| 成本 | 低:单个 transform | 高:需要分层结构 + preserve-3d,且有栅格化发糊问题(§3.4) |
| 选型规则 | 内容是平面信息(界面、文档、图表)→ zoom | 内容有明确的「前景/主体/背景」层次,且这层次值得被看见 → dolly |
3D 真假裁决(化解本 skill 两处旧文矛盾的边界线):
镜头运动和元素动画不许抢同一个 transform。所有镜头级运动收口到一个专职容器上。
<div id="viewport"> <!-- 固定视口,overflow: hidden,持有 perspective -->
<div id="camera"> <!-- 镜头层:只承载相机 transform,别的什么都不干 -->
<div id="world"> <!-- 世界层:所有画面内容住这里,元素动画只动 world 内部 -->
...场景内容...
</div>
</div>
<div id="hud"> <!-- 字幕 / 角标 / chrome:与 #camera 平级,天然不跟镜头动 -->
</div>
</div>
分工铁律:
#camera 上只出现镜头 tween(translate / scale / rotate / zoom 属性),元素入场、stagger、
hover 态一律写在 #world 内部的元素上。两层互不知晓,镜头随时可以整体重排而不碰元素动画#hud,零成本保持静止;只有「必须跟着 world 里某元素走、
但字号要恒定」的标注(如跟随 tooltip),才在该元素上做 counter-transform:
scale(1/zoom) 反向抵消镜头缩放,每帧与相机同步更新把镜头状态定义成关键帧对象,镜头运动 = 关键帧之间插值:
{ frame, cx, cy, zoom, rotX, rotY, rotZ, persp }
cx/cy 是世界坐标系里镜头对准的点,zoom 是倍率。以 1920×1080 画布为例 (其他尺寸把 960/540 换成 W/2、H/2):
平面模式(无旋转,纯 zoom + pan):
transform: translate(960 − cx·zoom, 540 − cy·zoom) scale(zoom)
transform-origin: 0 0
3D 模式(有 rotX/rotY/rotZ):
外层(#camera): perspective: persp·zoom; perspective-origin: 960px 540px
内层(#world): zoom: {zoom}; /* 注意是 CSS zoom 属性,见 §3.4 */
Tx = 960/zoom − cx; Ty = 540/zoom − cy
transform: translate(Tx, Ty) rotateY() rotateX() rotateZ()
transform-origin: cx cy
transform-style: preserve-3d
典型机位参数 (shotcraft 实测):全页 zoom 0.78 → 特写 2.6; 侧拍 rotY34 / rotX8 / persp1200(侧拍优于俯拍,rotY 主导 + rotX 只给一点); orbit 起止机位见 §1 表。
#world 必须比视口大(四周外扩 bleed ≥ 最大 pan 振幅 + 8% 边距),
否则平移时露出画布外的空白。这是 A1 可见性公理的反面:不该看的也不能看见#camera 与 #world 之间的任何中间层加了
overflow: hidden、filter、opacity <1 都会创建新 stacking context,
杀掉 preserve-3d,3D 分层瞬间变平。3D 模式下滤镜效果只加在最内层元素上问题:3D 模式下用 transform: scale() 放大页面,Chromium 按元素的布局尺寸栅格化,
再把位图放大,文字必糊。倍率越高糊得越狠,2x 以上不可交付。
解法:放大不走 transform: scale,走 CSS zoom 属性。zoom 是布局级缩放,
Chromium 按放大后的尺寸重新 layout 并栅格化,文字在任意倍率下保持矢量级锐利。
§3.2 的 3D 模式公式里内层写 zoom: {zoom} 而不是 scale({zoom}),正是为此。
配套要点:
| 要点 | 做法 | 出处 |
|---|---|---|
| 坐标补偿 | zoom 改变布局坐标系,translate 量要除以 zoom:Tx = 960/zoom − cx(§3.2 公式已含) |
(shotcraft) |
| 与 reflow 禁令的关系 | gsap-recipes §6.2 禁 tween 布局属性是因为整数 snap 抖动;zoom 是整页级缩放,snap 量不可感,且文字锐利收益远大于。此技法是 §6.2 的唯一合法例外,只用于 #world 相机层 |
(实测) |
| 渲染环境 | HyperFrames / Playwright 离线逐帧 seek 渲染下完全适用:每帧重 layout 的耗时不影响产物,只影响渲染时长。实时浏览器 preview 可能掉帧,属正常,以渲染产物为准 | (shotcraft) |
| 位图素材增强 | 全页截图用 2x 采样;特写元素另备 4x 单独截图,在推进期用 6f 交叉淡入盖住低倍纹理 | (shotcraft) |
| 景深氛围 | DoF 只做氛围:顶部渐变带 blur + mask,不做逐层真实景深 | (shotcraft) |
| 场景 | easing | 调节手感 |
|---|---|---|
| 主动运镜(推近/拉远,有明确起止点) | cubic-bezier(0.65,0,0.35,1) = GSAP power3.inOut |
两端都稳,「导演给镜头」的感觉;绝不线性、绝不弹簧过冲 (HuaRec) |
| 跟随式运镜(镜头追一个已开始的动作) | cubic-bezier(0.33,0,0.15,1) |
出发轻快、刹车极长,镜头像「跟上去」而不是「切过去」;shotcraft 相机默认 |
| 持续漂移(idle drift、匀速巡览) | sine.inOut yoyo 或 none |
唯一允许相机匀速的场景(gsap-recipes §1 既有规则);有起止点的动作禁用 |
| 光标/焦点跟随平滑 | quickTo + ~0.15s 平滑;路径插值 Catmull-Rom |
前向+后向 EMA 的零相位思路:跟得紧但不抖 (HuaRec) |
两套默认冲突时的裁决:单次推拉信 HuaRec(power3.inOut),复合移动、 多段连续镜头信 shotcraft(0.33,0,0.15,1)。
所有推拉时长由倍率变化量决定,保证任何幅度的 zoom「视觉速度」一致:
duration = 0.55 × |ln(zoom₂ / zoom₁)| / ln 2 clamp 到 [0.30, 0.94] 秒
1→2x 推近正好 0.55s;1→1.3x 约 0.30s(触底);0.78→2.6x 触顶 0.94s。(HuaRec) 大景别过渡更久、小景别更短,防「一蹿到位」也防「拖沓」。
| 档位 | 倍率 | 用途 | 调节手感 |
|---|---|---|---|
| 定场微推 | 1.06x | 仅用于开场定场(§6),观众感知不到 zoom、只感知到「画面活着」 | 唯一允许低于 1.25x 的档位 (HuaRec) |
| 轻推 | 1.3x | 提示性聚焦:不打断全局阅读,只是「注意这一片」 | |
| 中推 | 1.45x | 标准 UI 特写:一个面板 / 一段代码 | |
| 重推 | 1.8x | 单元素特写:一个按钮 / 一个数字 | 克制档的上限 (HuaRec) |
| 上限 | 2.3x | 极限特写,素材必须扛得住(2x 截图 / 4x 切片,§3.4) | 超过就换素材,不硬推 (HuaRec) |
定景公式 (HuaRec):scale = 0.8 / max(目标包围盒归一化宽, 高),再夹到档位区间。
内容占可视区 80%,留 20% 呼吸,不顶格。
晕不是单个镜头造成的,是镜头之间的接法造成的。 「出-进-出」泵动和远焦点连续横跳 贡献了绝大多数眩晕感 (HuaRec)。对相邻两镜(间隔 <1.5s),按焦点距离三分:
| 焦点归一化距离 | 接法 | 说明 |
|---|---|---|
| <0.22(近) | 并镜 | 合并为一镜:取两目标的联合包围盒重算倍率,一镜看完 |
| 0.22-0.45(中) | 改平移 | 宁可倍率广一点(联合倍率 ≥1.25),一镜平移过去,不做「出再进」 |
| >0.45(远/对角) | 弃镜 | 砍掉动机更弱的那一镜。绝不连拍两个远焦点,对角横跳是最晕的一种接法 |
补两条时序规则 (HuaRec):
三条语法成本极低,作品感提升明显 (HuaRec):
转场是独立层:接缝按能量落差选型,一个接缝只用一式,转场帧从相邻镜头预算里划走。 「公认优秀的发布片全程没有一次裸切」(shotcraft)。
| 式 | 适用能量落差 | 参数 | 坑 |
|---|---|---|---|
| 流白 flash-wash | 高→高,段落强转 | 白场 2-4f 峰值,两侧各 5f 渐变 | 白闪只盖切点,不当装饰反复用 |
| 穿暗场 dip-to-dark | 高→低,情绪降档 | 压暗到 rgba(20,20,20,0.9) 量级,总长 ≤0.6s | 暗场里别停留,观众以为片子结束 |
| 虚焦接力 defocus-handoff | 中→中,平级话题切换 | 出镜 blur 0→8px 与入镜 blur 8px→0 交叠 ≥8f | blur 大面积 ≤24px(DoF 性能约束) |
| 黑场字卡 title-card | 章节级分隔 | 字卡 hold ≥1s,前后各 0.3s 过渡 | 全片 ≤2 张,多了像幻灯片 |
| whip-pan 甩镜 | 低→高,能量急升 | 两端 hold ≥20f → 8f 甩 1.5 屏,峰值 ≥300px/f 才糊得透 (shotcraft) | 慢了就是普通 pan,糊不透反而露拙 |
| mask-wipe 穿窗 | 空间转移,「穿过一个界面进入另一个」 | 遮罩缘 easing (0.4,0,0.6,1) (shotcraft) |
遮罩形状必须来自画面内已有元素(窗口/卡片圆角),凭空的形状是 slop |
| 式 | 做法 | 出处 |
|---|---|---|
| flash-cut 白闪跨切 | 白闪跨骑硬切点,两侧各 5f,只盖切点 | (shotcraft,实证参数) |
| 前景遮挡切 | 一个前景元素(卡片/面板/光标手)扫过全屏的瞬间换景 | (推测:通用电影语汇,参数待实测) |
| 运动糊切 | 高速运动峰值帧上硬切,两侧运动方向一致,motion blur 吞掉切点 | (推测:通用电影语汇,参数待实测) |
| 式 | 做法 | 坑 |
|---|---|---|
| 共享元素归位 | 前镜的某元素(logo/卡片)连续运动到后镜中它的新位置,FLIP 思路的镜头版 | 元素在两镜中必须同一身份,形变过大就断了「同一个东西」的认知 |
| 字腔穿越 | 镜头推进穿过大字的字腔(O/口/0 的空洞)进入下一场景 | 字腔尺寸要够(≥1/3 屏高),穿越段 zoom 走对数时长上限 0.94s |
选型速查:能量落差大 → 六式挑一;不想被察觉 → hidden-cut;两个场景空间上连续 → travel。 硬切不是禁用,是「必须被上述任意一层包装过」。
| 参数 | 典型值 | 调节手感 |
|---|---|---|
| 层速度系数 | 远景 0.35 / 中景 0.7 / 近景 1.4(相机位移的倍数) | 相邻层速比 ≥2 倍才可辨,1.2 倍的差异观众读不出来 |
| 层数 | ≤4 层 | 超过 4 层的视差没人看得出来,纯浪费预算 |
| 实现 | 各层根据同一个相机 x/y 乘各自系数 translate | 全部由相机状态推导,seek-safe;别给每层独立 tween |
主体:钉死不动(或只做 ≤1.02x 的呼吸)
背景:scale 1 → 2.0-2.5,同时 opacity 降到 ≤0.6
主体不变、背景涌向观众,产生「世界在逼近而主角凝固」的反转感 (shotcraft)。 时长给足(≥1.2s),用途见 §1:全片最多一次,留给真正的揭示瞬间。
镜头的「速度感」不靠更快的 duration,靠从速度派生出来的次级信号 (shotcraft / HuaRec):
| 信号 | 公式 | 参数 |
|---|---|---|
| 速度驱动 blur | v = velocityAt(f)(中央差分:(pos(f+1)−pos(f−1))/2),blur 强度 ∝ v |
zoom 速度 >0.6/s 才触发,强度 min(10, v×5)px。只在动的瞬间有模糊,静止帧永远锐利 (HuaRec) |
| lagged 跟随层 | 跟随层 = 主体在 f − delay 处采样 |
阴影滞后 2f、残影滞后 4f (shotcraft)。残影平替 motion blur:5% 路径滞后 + blur(6px) + opacity 0.25·(1−t) |
| dampedSettle 余震 | e^(−d·t) · sin(2π·f·t),f≈0.1、damping≈0.15 |
镜头急停后的 1-2 个微小残摆,幅度 ≤3px;主动运镜(§4.1 inOut 族)不加,只给 whip-pan / 急刹类 |
三者全部是时间的纯函数(差分、延迟采样、闭式衰减),天然 seek-safe, 符合 gsap-recipes §6 的确定性要求。
#camera 层,没和元素动画抢 transform?| reference | 分工 | 边界 |
|---|---|---|
animation-best-practices.md |
元素怎么动、叙事节奏、品味标准 | 它管「演员」,本文件管「摄影机」;S4 爆发段的「镜头拉远」按本文件 §4 定参数 |
gsap-recipes.md |
本文件所有规则的 GSAP 可运行实现 | 「Camera Rig 配方」节:rig 容器、PageCam 翻译、对数时长 helper、counter-transform |
animation-pitfalls.md |
踩坑清单 | 镜头专属坑(scale 发糊 / perspective 被打断 / pan 露边)§3.3-3.4 已覆盖设计侧,pitfalls 收技术侧复现 |
hyperframes-backend.md |
渲染后端契约 | CSS zoom 技法在离线逐帧渲染下的适用性见 §3.4 |
voiceover-pipeline.md |
解说驱动长视频 | move on pause(§6.3)的静默点数据从 narration 分句间隙来 |
ai-video-review.md |
成片评审 | 评审 checklist 的转场分类按 §7 三层词汇扩展 |
调用顺序:导演稿 / 分镜阶段读 §0-§2 定预算和词汇 → 写 timeline 前读 §3-§7 定实现约定 与接缝 → 交付前过 §10 清单。