givemotion: HTML 进,视频出
一个合成就是一个 HTML 文件。每一帧都是该页面在某个时间点的状态。CSS 动画、过渡、Web 动画、定时器、requestAnimationFrame、Canvas 和 WebGL 都在一个虚拟时钟上运行,因此你编写的内容会以帧精确且每次完全相同的方式渲染。无需脚本标签或导入:运行时 (window.gm) 和一个预设样式表已为你注入。
此文件是核心(请通读)。然后只阅读你的视频所需的 1-3 个技巧配方(见末尾表格):每个配方都展示了专业人士如何构建该效果,附带数字和一个可用的示例。需要时再查阅其他内容。
循环
- 方向。 在代码之前,决定顶级工作室会如何制作这份简报:研究类型(尽可能在网上搜索真实示例,否则回忆它们),然后在 HTML 顶部写下:视觉风格描述、字体系统、运动语言(缓动族、节奏、场景如何交接)以及镜头列表(每个时刻一行:时间、屏幕上有什么、运动、交接)。如何做:
references/direction.md。 - 风格帧。 先构建 2-3 个关键静止帧,保持静止,并用
still命令逐个判断:将它们视为海报(一个焦点、层级、边距)。然后制作动画。 - 编写运动;边编写边运行
npx givemotion check video.html:修复每一个 ✖;⚠ 是真正的故障(除非有意为之);ℹ 是样式提示。 - 两次审查。 运行
npx givemotion review video.html会写入观众所看到的内容(概览、观众阅读的帧、繁忙时刻的运动条)以及review/REVIEW.md:严格评分,修复五个最严重的问题,然后再次审查。新的视角会发现更多:将简报和审查文件夹仅提供给子代理。将简报的时间放入data-expect。 - 渲染:
npx givemotion render video.html -o out/video.mp4。
--json 用于机器输出,<command> --help 查看选项。still video.html -t 3.2 -o f.png 渲染单个时刻;inspect --at 4.5 --el "#logo" 返回元素的位置。
如何在这里制作出色的运动
引擎提供任何 HTML/CSS/SVG/Canvas 和一个帧精确的时间轴;视觉效果取决于你如何编排。盲人观众更喜欢手动编排每个元素的视频,而不是使用一个词预设构建的视频。
- 手工编排。 对任何重要的事情使用
gm.timeline:明确的开始时间、每个动作的缓动(快速的expo.out猛击、柔和的sine.inOut漂移、back.out(1.6)着陆)、相关部分之间 40-120 毫秒的偏移。预设(data-enter、data-camera)适用于小的辅助元素。 - 每个英雄时刻有三层: 主要运动;出卖它的次要细节(快速时模糊、光晕、增长的阴影、跟随动作、撞击时的环或粒子);以及环境运动,使画面永不冻结(漂移的背景、缓慢的镜头推进)。
- 时间对比。 快速进入,缓慢稳定;运动结束后停留 0.4-1 秒;离场时间短于入场时间。切勿让所有东西以相同的速度和相同的曲线运动。
- 严格遵循简报 中的颜色、字体、文案、尺寸和时机;你的技艺体现在事物如何运动,而不是额外的内容。
- 第 0 帧是钩子,没有任何内容被画面边缘裁切,文字要大(标题 96-200 像素,正文在 1080p 下 ≥ 36 像素),每个时刻只有一个英雄,场景相互流动(推、甩、变形、匹配切换),而不是淡入淡出。
- 事物从其他事物中产生。 一个新元素由屏幕上已有的元素诞生,而不是凭空出现:三个圆圈从主圆圈中挤出;屏幕上的一个矩形滑过并成为下划线;一张卡片从被点击的按钮中长出;Logo 的标记成为尾卡的标记。在添加之前,重用和变换。提前埋设下一组: 在这个节拍播放时,它们已经存在于世界中(小、暗),以便镜头揭示它们。
- 镜头移动意味着“看这里”。 只有当观众需要阅读某个内容时才向它推进。切勿放大到空白区域或旧场景中作为过渡方式:要离开场景,横向移动(推、甩、擦)或携带一个元素穿过(变形,上述规则)。
- 动画化
transform/translate/scale/rotate/opacity/filter/clip-path,而不是width/top/left。 - 每个元素都有一个计划的生命周期: 入场、一个可读的停留(约 1 秒 + 每个词 0.25 秒),然后离场或交接。镜头列表给出了每个停留时间。
层次:一次只关注一件事
观众更喜欢眼睛始终知道看哪里的视频。
- 每行都有一个关键词。 赋予承载意义的词语以对比(强调色、更粗的权重、更大的尺寸,或绘制的突出显示);其余部分保持安静。每行一个,每个屏幕最多两个。如果一切都是强调,那就没有强调了。
- 每个时刻只有一个英雄: 最大、最亮、运动最多的东西。辅助元素更小(英雄 ≥ 下一尺寸的 1.6 倍;最多三级)、更暗(柔和或 50-70% 透明度)、在英雄之后到达且运动更少。效果(环、火花)环绕英雄,从不穿过它。
- 按顺序引导视线: 英雄先着陆;关键词在其行稳定后 0.2-0.4 秒获得颜色或下划线;辅助元素跟随。当镜头或标注聚焦于某物时,将其他部分调暗。
- 调色板角色严格: 强调色仅用于强调,柔和色用于次要文本。
缓动:使曲线与运动匹配
- 入场 减速(缓出:
expo.out、power3.out,或者当它带重量着陆时用back.out(1.4))。 - 离场 加速(缓入:
power2.in),比入场短(60-70%)。 - 从 A 到 B 的移动 (当可见时)、镜头移动、屏幕上已有对象的缩放变化:缓入缓出(
power2.inOut、sine.inOut):它温和地开始并温和地着陆。 - 环境漂移: 长时间的
sine.inOut;linear仅用于循环(旋转、滚动条)。没有在屏幕上开始或停止的移动是线性的。 - 省略
ease,引擎已经为你做了这些(入场弹入,移动缓入缓出,离场缓入);当你设置一个时,遵循上述规则。
最小合成
<!doctype html>
<html data-width="1920" data-height="1080" data-fps="30" data-duration="2.5">
<head>
<style>
:root { --bg: #0b0d12; --ink: #fff; --accent: #7c9cff; }
body { background: var(--bg); color: var(--ink); font-family: Inter, sans-serif; }
.scene { display: grid; place-items: center; } /* .scene 已经是 absolute + 全屏 */
h1 { font-size: 160px; letter-spacing: -0.03em; margin: 0; }
.glow { position: absolute; width: 900px; height: 900px; border-radius: 50%; background: var(--accent); filter: blur(160px); opacity: .25; }
</style>
</head>
<body>
<section class="scene">
<div class="glow"></div>
<h1 id="t" data-split="chars">Hello</h1>
</section>
<script>
gm.timeline('.scene')
.from('.glow', { scale: 0.6, opacity: 0, duration: 1.2, ease: 'sine.out' }, 0) // 环境:光晕绽放…
.to('.glow', { x: 220, y: -90, duration: 2.5, ease: 'sine.inOut' }, 0) // …并持续漂移
.from('#t .gm-char', { y: 140, opacity: 0, filter: 'blur(12px)', duration: 0.7, ease: 'expo.out', stagger: 0.05 }, 0.2) // 主线:快速进入,快速时模糊
.fromTo('#t', { letterSpacing: '0.12em' }, { letterSpacing: '-0.03em', duration: 2.4, ease: 'expo.out' }, 0.2) // 细节:字间距收紧
.to('#t', { scale: 1.06, duration: 1.9, ease: 'sine.inOut' }, 0.6); // 停留持续呼吸
</script>
</body>
</html>
内置字体:Inter、JetBrains Mono、Playfair Display、Space Grotesk、Bebas Neue、Nunito、Caveat;其他字体通过 @font-face 引入。
时间模型(阅读此部分)
- 设置位于
<html>上:data-width、data-height(偶数)、data-fps(默认 30)、可选data-duration、可选data-background。 - 时间单位为秒:
1.5、1.5s、500ms、45f(帧)、1:02.5。 - 剪辑。 带有
data-start、data-duration或data-end的元素仅在其剪辑从 start 到 start+duration 的时间内存在(display显示)。时间相对于其父剪辑。没有时间设置的元素始终存在。 - 视频长度 =
<html>上的data-duration,否则为最后一个剪辑的结束时间。 - 序列。 容器上的
data-sequence会依次播放其子元素。每个子元素都需要data-duration,或者为容器指定data-cuts="0 2.13 4.27"(每个子元素开始的时间;也可以是"beats: 0 4 8"/"bars: 0 1 2")。data-gap="0.2"(负值表示重叠)。data-transition="<名称> <秒数> [缓动]"会使相邻元素重叠并动画化变化;子元素可以设置自己的data-transition(它如何进入)。每个转场都会从总时长中扣除其长度:3 个 4 秒的场景,带有fade 0.5,总时长为 11 秒。在节拍上切换、data-cut-align,以及场景时间 0 的位置:references/timeline.md。 - 转场:
push-/cover-/whip-/wipe-+left/right/up/down(push:新场景推出旧场景;cover:新场景滑过旧场景;whip:快速、模糊)diagonalclockiriszoomzoom-through(旧场景飞过镜头)flip(3D)dip(通过黑色)blurfade-upfade,以及morph:两个场景中具有相同data-morph="name"的元素会从旧位置飞到新位置并调整大小,同时其余部分交叉淡入淡出。能在场景间携带 Logo、卡片或数字;在一个场景内使用gm.fly。 - CSS 动画在剪辑时间内运行。
animation: fade-up .6s .4s both在其剪辑出现后 0.4 秒开始。使用both(或backwards)填充模式,以便元素在延迟前是隐藏的。 - 在长场景内部,某物稍后出现(一个镜头世界,一个白板):
data-enter中的延迟从元素剪辑的开始算起,因此data-enter="write 0.8 11.9"会在场景开始 11.9 秒后才写入标签并将其隐藏到那时。无需额外的剪辑。 gm.onFrame(fn)获取视频的时间,即使在场景内也是如此;gm.onFrame('#s', (local, info, el) => …)从#s的开始算起,类似于gm.timeline('#s')。- 定时器、
requestAnimationFrame、Date.now()、performance.now()都是虚拟的,并且Math.random()是种子化的。普通的 Web 动画代码可以正常工作。
时间轴:精确编排(GSAP 风格,内置)
对于任何有多个移动部分的情况,使用 gm.timeline:你熟悉的 GSAP API,根据时间计算(帧精确,并行)。时间单位为秒,相对于包含该作用域的剪辑。
gm.timeline('#scene2') // 作用域:选择器在其内部查找
.from('.title .gm-word', { y: 120, opacity: 0, rotate: 8, stagger: 0.06 }) // 无缓动:弹入
.to('.card', { x: 400, y: -60, scale: 1.2 }, '+=0.3') // 弧形,大小随距离调整
.fromTo('.bar', { scaleY: 0 }, { scaleY: 1, stagger: { each: 0.08, from: 'center' } }, '<')
.to('#line', { draw: 1, duration: 1.5 }, 2) // 绘制 SVG 描边
.to('.price', { textContent: 249, duration: 1.5 }, 2.5); // 数字计数
gm.fly('#event', { from: '#slot2', at: 7.5, duration: 0.8 }); // 从另一个元素的盒子飞到自己位置
from()/fromTo() 会从其剪辑的开始阶段显示起始值(在它们进入前隐藏)。重叠的补间动画作用于同一属性:最新开始的获胜。位置、所有属性和选项、标签、关键帧、gm.fly 和 SVG 注意事项:references/timeline.md。
此外还有内置功能(references/api.md 中的表格):data-enter/data-exit 预设、data-split、data-stagger、data-count (-roll)、data-type(打字机)、data-scramble、data-camera(推、浮动、抖动…)、data-parallax、data-morph、data-fit、data-pulse、缓动名称(GSAP 名称有效)、预设 CSS 关键帧和 var(--px),以及现成的代码块(npx givemotion blocks:字幕、代码窗口、光标、浏览器窗口、图表…)。
技巧配方(阅读你的视频需要的配方)
| 你的视频包含… | 阅读 |
|---|---|
| Logo、品牌标识动画、开场或尾卡 | references/techniques/logo-reveal.md |
| 大号字体猛击、堆叠、旋转;标题为主角 | references/techniques/kinetic-type.md |
| 文字揭示:词语/字符、打字机、写上去、乱序、高亮 | references/techniques/text-reveals.md |
| 镜头移动:推、跟随、甩、平移、缩放到细节、抖动 | references/techniques/camera-moves.md |
| 多个场景交接(推、甩、变形、形状擦拭) | references/techniques/scene-transitions.md |
| 光晕、光扫描、渐变、颗粒、模糊、深度 | references/techniques/light-and-depth.md |
| 数字、计数器、条形/折线图、标注 | references/techniques/numbers-and-charts.md |
| 绘制线条、路线、地图、图钉、沿路径移动的物体 | references/techniques/paths-and-maps.md |
| 平面形状:生长、挤压、分裂、轨道、变形 | references/techniques/shapes-and-motion-graphics.md |
| 包含光标、点击、打字、列表的应用/UI | references/techniques/ui-demo.md |
| 编辑器中的代码、打字、行突出显示 | references/techniques/code-on-screen.md |
| 冲击和能量:猛击、抖动、爆发、音乐节拍 | references/techniques/impacts-and-energy.md |
| 逐字字幕、垂直 9:16 短片 | references/techniques/captions-vertical.md |
| 白板、草图、手绘 | references/techniques/hand-drawn.md |
| 所有内容背后的生动背景 | references/techniques/backgrounds-and-ambient.md |
API 参考(需要时查阅)
| 当… | 阅读 |
|---|---|
| 属性、预设、缓动名称、预设 CSS 或代码块 | references/api.md |
gm.timeline 完整文档:位置、关键帧、标签、gm.fly、SVG | references/timeline.md |
gm.camera 世界、镜头、gm.path.travel、跟拍、视差 | references/camera.md |
gm.chart.*、图表代码块 | references/charts.md |
图表、箭头、data-sketch、gm.connect、gm.shape、路径变形 | references/diagrams.md |
音乐、节拍、画外音 + givemotion words、视频片段、字幕 | references/media-audio.md |
数据/模板、<gm-in |
…
[已截断]