Motion · Tipografia
Scramble decode vs letter drop
Two title-entrance moves — scramble-decode (an answer grows out of noise) and letter-drop-physics (letters drop with gravity, bounce, and settle), picked by tone.
Fonte: video-shotcraft (Vincent Wei) ↗ · Apache-2.0 · Composição Remotion (React/TSX) — vídeo de prévia, sem player no navegador
Variantes
全员字符高速跳乱码 hold,随后从左到右逐个锁定真字符,锁定瞬间反色闪 2f,底部进度条同步推进
技术/开发者产品;"答案浮出"的理性推进感
字符错峰从顶砸落,重力加速+两次衰减弹跳+落地歪斜站定,最后一拍全体齐整回正
轻松调性开场;"活物感"的标题破冰
When to use
Big-title/chapter text-card entrances; mutually exclusive with split-flap-title (mechanical flip) and document-typewriter-reveal (typewriter) in the same category
Intention
Title entrances already have the typewriter (a steady, document feel) and the split-flap board (a mechanical-ceremony feel) — these two styles fill in two more personalities: A is a terminal-hacker feel — every letter starts as a burst of noise, "decoding" one by one from left to right as the viewer watches the answer grow out of the garble, good for a confident reveal on tech products; B is physical-comedy feel — letters drop from above, hit the ground, bounce and wobble upright, then snap together into formation on the final beat, good for a light-toned icebreaker opener. At most 2 of the four title-entrance moves per film (P4).
Duration & energy
- Duration: Single style 4–5s (including hold and still close; action segment A ~66f / B ~106f)
- Energy: Medium-high (A leans rational and driving, B leans physical and playful)
Shot recipe (original Chinese — timing, easing, parameter table, known pitfalls)
意图
标题入场库内已有打字机(沉稳文档感)和翻牌屏(机械仪式感),这两式补 另外两种性格:A 是终端黑客感——字符先是一片高速噪声,从左到右逐个 "解码"锁定,观众看着答案从乱码里长出来,适合技术产品的自信亮相; B 是物理喜剧感——字符从天而降、砸地弹跳、歪歪扭扭站定,最后一拍 集体立正归位,适合轻松调性的开场破冰。四种标题入场同片 ≤2 种(P4)。
两式选型
| 式 | 做法 | 适用 | |----|------|------| | A scramble-decode 乱码解码 | 全员字符高速跳乱码 hold,随后从左到右逐个锁定真字符,锁定瞬间反色闪 2f,底部进度条同步推进 | 技术/开发者产品;"答案浮出"的理性推进感 | | B letter-drop-physics 字符坠落 | 字符错峰从顶砸落,重力加速+两次衰减弹跳+落地歪斜站定,最后一拍全体齐整回正 | 轻松调性开场;"活物感"的标题破冰 |
参数表
| 参数 | 典型值 | 调节手感 | |------|--------|----------| | A 乱码期 | 0–20f 全员每 2f 跳一个随机字符(字符集 A–F/0–9/#$%&),字色 G.mid | 必须用等宽字体 + 固定 1ch 槽宽,比例字体每跳一下整行抖动 | | A 解码节拍 | 第 i 字符帧 20+i×6 锁定为真字符转深色;锁定后前 2f 反色闪(深底白字) | 6f/字是"逐个可辨"的下限;上限 10f,再慢读作卡住 | | A 伪随机 | CHARSET[floor(h(i*101+floor(f/2)*7+13)*len)],h = sin hash | 严禁 Math.random——跳动必须随帧确定,否则渲染不可复现 | | B 坠落 | 第 i 字符帧 10+i×5 起跳;y = −DROP + DROP·(t/24)²(重力)→ 4u(1−u) 抛物线弹跳 30% → 二跳 9% | 弹跳衰减比 30%/9% 是"有弹性但不闹"的甜点;三跳以上读作果冻 | | B 歪斜 | 落地瞬间 rotate 到 seed hash ±6° 并保持 | 歪角是"物理感"的一半;全体笔直落地读作普通位移入场 | | B 归位一拍 | 全员落定后(如帧 110)6f ease-out 集体 rotate→0 + scale 1.06→1 | 集体归位是句号——错峰归位会把"立正"的仪式感拆散 | | 收尾 | 两式动作完毕真静止 ≥20f | R1:静止期所有属性锁死(含 B 的歪角归零后) |
已知坑
- demo 在灰阶/占位素材上调校通过——参数是调校起点非实战定稿,
首次实战须以真实素材回验
- A 式是声音强依赖候选位:锁定的"嗒"声逐字钉帧(sound-design §4.5)
会让解码感翻倍;B 式落地砸声同理,无声版两式都还成立但少一半劲
- A 式字符集别混入与真字符太像的字形(如 O/0 连跳)——观众会误判已锁定
- B 式字符间不做真实碰撞(demo 为各字符独立轨迹)——字距排开即可;
想要"互相撞歪"需预烘焙轨迹,成本高收益薄
- 标题入场品类已四式(本卡两式 + split-flap-title + document-typewriter-reveal),
同片 ≤2 种,且都自带高注意力——别和其他高能量入场同帧抢戏
参考实现
demos/typography/type-entrance-moves/ (LetterDropPhysics.tsx / ScrambleDecode.tsx)
Reference implementation (Remotion)
- demos/typography/type-entrance-moves/LetterDropPhysics.tsx — https://raw.githubusercontent.com/Vincentwei1021/video-shotcraft/main/demos/typography/type-entrance-moves/LetterDropPhysics.tsx
- demos/typography/type-entrance-moves/ScrambleDecode.tsx — https://raw.githubusercontent.com/Vincentwei1021/video-shotcraft/main/demos/typography/type-entrance-moves/ScrambleDecode.tsx
The component imports shared fixtures from demos/_fixtures and helpers from assets/lib in the repo; SKILL.md there documents the render workflow.
Tudo nesta página também é legível por máquina. Aponte seu agente para o JSON ou adicione o servidor MCP do gimgs e peça para buscar templates de motion.
- Baixe o JSON — contém a receita do plano (timing, easing, tabela de parâmetros, armadilhas) e o código TSX completo.
- Clone o repositório video-shotcraft; o componente importa fixtures de demos/_fixtures e helpers de assets/lib.
- Registre o componente como <Composition> em um projeto Remotion e renderize com `npx remotion render`, ou reimplemente a receita no seu próprio engine.
curl -s https://gimgs.net/motion/type-entrance-moves.jsongit clone https://github.com/Vincentwei1021/video-shotcraft
# component: demos/typography/type-entrance-moves/LetterDropPhysics.tsx, demos/typography/type-entrance-moves/ScrambleDecode.tsx
npx remotion render <CompositionId> out.mp4claude mcp add --transport http gimgs https://gimgs.net/mcp
# then: search_motion_templates / get_motion_template("type-entrance-moves")Prompt
Use the video-shotcraft shot recipe "Scramble decode vs letter drop" (Remotion composition, Apache-2.0) published on gimgs.net. Recipe JSON (prompt = timing/easing/parameter table/pitfalls, files = TSX source): https://gimgs.net/motion/type-entrance-moves.json Raw TSX: https://gimgs.net/motion/type-entrance-moves/template.html Repository: https://github.com/Vincentwei1021/video-shotcraft (component: demos/typography/type-entrance-moves/LetterDropPhysics.tsx, demos/typography/type-entrance-moves/ScrambleDecode.tsx; imports demos/_fixtures and assets/lib) Spec: 1920x1080, 30 fps, 4.39s 1. Read the JSON and follow its "prompt" section (when to use, intention, parameter table, known pitfalls). 2. Adapt it for: <describe what you want>. 3. Either clone the repo, register the component as a <Composition> in a Remotion project and run npx remotion render <CompositionId> out.mp4 — or re-implement the recipe in your own engine (HTML/WAAPI works: keep the same timing and easing).
// ===== demos/typography/type-entrance-moves/LetterDropPhysics.tsx =====
// 字符坠落堆积(letter-drop-physics)——FallingLetterAnimation。
// "GRAVITY" 7 字符各自绝对定位,第 i 字符从帧 10+i*5 起下落:
// ① 重力加速 y = D*(t/24)^2 掉 720px 到基线(地板线可见);
// ② 落地后 2 次衰减弹跳(高度 30% / 9%,抛物线 4u(1-u) 拼段),
// 落地瞬间 rotate 到 seed hash ±6° 小歪角并保持;
// ③ 帧 110 一拍:6f ease-out 全体齐整回正(rotate→0、偏移→0、scale 1.06→1),
// 帧 116–150 真静止(≥25f)收尾。
import React from 'react';
import { useCurrentFrame, Easing } from 'remotion';
import { G } from '../../_fixtures/Fixtures';
// 确定性伪随机
const h = (n: number) => {
const s = Math.sin(n * 127.3) * 43758.5453;
return s - Math.floor(s);
};
const WORD = 'GRAVITY';
const SLOT_W = 150; // 每字符槽宽
const FONT = 140;
const WORD_W = WORD.length * SLOT_W; // 1050
const LEFT = (1920 - WORD_W) / 2; // 435
const REST_TOP = 452; // 字符落定后的 top
const FLOOR_Y = REST_TOP + 152; // 地板线(视觉基线)
const DROP = 720; // 下落距离
const T_FALL = 24; // 落到基线用时
const T_B1 = 16; // 第一次弹跳时长(高 30%)
const T_B2 = 8; // 第二次弹跳时长(高 9%)
const SNAP = 110; // 齐整回正的一拍
const SNAP_DUR = 6;
const easeOutCubic = Easing.out(Easing.cubic);
const clamp01 = (x: number) => Math.min(1, Math.max(0, x));
// 单字符纵向位移(相对基线,负 = 在上方)
const dropY = (t: number): number => {
if (t <= 0) return -DROP;
if (t < T_FALL) return -DROP + DROP * (t / T_FALL) ** 2; // 重力加速
if (t < T_FALL + T_B1) {
const u = (t - T_FALL) / T_B1;
return -DROP * 0.3 * 4 * u * (1 - u); // 弹跳 1:30%
}
if (t < T_FALL + T_B1 + T_B2) {
const u = (t - T_FALL - T_B1) / T_B2;
return -DROP * 0.09 * 4 * u * (1 - u); // 弹跳 2:9%
}
return 0;
};
export const LetterDropPhysics: React.FC = () => {
const frame = useCurrentFrame();
// 帧 110 起的齐整回正进度
const snap = easeOutCubic(clamp01((frame - SNAP) / SNAP_DUR));
return (
<div style={{ width: 1920, height: 1080, background: G.bg, overflow: 'hidden', position: 'relative' }}>
{/* 地板线:字符落点的视觉基线 */}
<div style={{ position: 'absolute', left: LEFT - 60, top: FLOOR_Y, width: WORD_W + 120, height: 6, background: G.bar, borderRadius: 3 }} />
{WORD.split('').map((ch, i) => {
const start = 10 + i * 5;
const t = frame - start;
const y = dropY(t);
// 落地瞬间歪到 seed 小角度(±6°),落地前为 0
const tiltTarget = (h(i + 1) - 0.5) * 12;
const landP = clamp01((t - T_FALL) / 6);
const restJitter = (h(i + 11) - 0.5) * 10; // 落定后的 ±5px 竖向错位
// snap 一拍:歪角与错位齐整归零,scale 1.06→1 脉冲
const rot = tiltTarget * landP * (1 - snap);
const jitter = restJitter * landP * (1 - snap);
const scale = frame < SNAP ? 1 : 1 + 0.06 * (1 - snap);
return (
<div
key={i}
style={{
position: 'absolute',
left: LEFT + i * SLOT_W,
top: REST_TOP,
width: SLOT_W,
height: FONT,
display: 'flex',
alignItems: 'flex-end',
justifyContent: 'center',
transform: `translateY(${y + jitter}px) rotate(${rot}deg) scale(${scale})`,
transformOrigin: '50% 100%',
fontFamily: 'Helvetica, Arial, sans-serif',
fontWeight: 800,
fontSize: FONT,
lineHeight: 1,
color: G.ink,
}}
>
{ch}
</div>
);
})}
</div>
);
};
// ===== demos/typography/type-entrance-moves/ScrambleDecode.tsx =====
// 乱码解码字(scramble-decode)——终端黑客感文字入场。
// 标题 "DECODE SPEED" 每字符先高速跳随机字母/数字(每 2f 换一个,seed hash 取字符),
// 从左到右逐个锁定:第 i 个字符在帧 20+i*6 锁定为真字符,锁定瞬间该字符反色闪
// (G.ink 色块白字 2f)随即恢复。跳动期字符 G.mid,锁定后 G.ink。
// 关键帧:0–20f 全员乱跳 → 20–86f 从左到右逐个锁定 → 87–130f 完全静止收尾。
import React from 'react';
import { useCurrentFrame } from 'remotion';
import { G } from '../../_fixtures/Fixtures';
const TEXT = 'DECODE SPEED';
const CHARSET = 'ABCDEF0123456789#$%&';
const LOCK_START = 20; // 第 0 个字符锁定帧
const LOCK_STEP = 6; // 相邻字符锁定间隔
const FLASH_LEN = 2; // 锁定反色闪持续帧数
// 帧确定伪随机
const h = (n: number) => {
const s = Math.sin(n * 127.3) * 43758.5453;
return s - Math.floor(s);
};
export const ScrambleDecode: React.FC = () => {
const frame = useCurrentFrame();
const chars = TEXT.split('');
const lockedCount = chars.filter((c, i) => c === ' ' || frame >= LOCK_START + i * LOCK_STEP).length;
const allLocked = lockedCount === chars.length;
return (
<div
style={{
width: 1920,
height: 1080,
background: G.bg,
display: 'flex',
flexDirection: 'column',
alignItems: 'center',
justifyContent: 'center',
gap: 48,
}}
>
<div
style={{
fontFamily: 'ui-monospace, Menlo, Monaco, monospace',
fontWeight: 800,
fontSize: 120,
letterSpacing: 2,
display: 'flex',
}}
>
{chars.map((ch, i) => {
if (ch === ' ') {
return <span key={i} style={{ display: 'inline-block', width: '0.7em' }} />;
}
const lockFrame = LOCK_START + i * LOCK_STEP;
const locked = frame >= lockFrame;
const flashing = locked && frame < lockFrame + FLASH_LEN;
// 跳动期:每 2 帧换一个伪随机字符
const tick = Math.floor(frame / 2);
const scrambleChar = CHARSET[Math.floor(h(i * 101 + tick * 7 + 13) * CHARSET.length)];
const shown = locked ? ch : scrambleChar;
return (
<span
key={i}
style={{
display: 'inline-block',
width: '1ch',
textAlign: 'center',
color: flashing ? G.card : locked ? G.ink : G.mid,
background: flashing ? G.ink : 'transparent',
}}
>
{shown}
</span>
);
})}
</div>
{/* 底部进度提示条:已锁定字符数比例,帮助读出"从左到右扫过"的推进感 */}
<div style={{ width: 900, height: 10, background: G.line, borderRadius: 5, overflow: 'hidden' }}>
<div
style={{
width: `${(lockedCount / chars.length) * 100}%`,
height: '100%',
background: allLocked ? G.ink : G.mid,
borderRadius: 5,
}}
/>
</div>
</div>
);
};
- Read the recipePrompt = when to use, intention, parameter table with typical values and how each one feels, known pitfalls. Treat values as calibrated starting points.
- Get the codetool: git
git clone https://github.com/Vincentwei1021/video-shotcraft && cd video-shotcraft && npm install - Register + rendertool: remotion
npx remotion render <CompositionId> out.mp4 # component: demos/typography/type-entrance-moves/LetterDropPhysics.tsx, demos/typography/type-entrance-moves/ScrambleDecode.tsx - Or re-implementPort the timing/easing from the recipe to HTML + WAAPI (gimgs motion contract) or any engine; keep the same segment windows and easing.
| param | type | default | description |
|---|---|---|---|
| — | |||
Mais nesta categoria

Word relay geometry
Three benefit words each carry their own dedicated geometry relay — a dashed circle spins and shrinks → three solid circles trim-grow in sequence → a metallic sheen sweeps then collapses to pure white; each new word outlines then fills in.

Word relay filmstrip
A left column of black-and-white page cards steps forward while a serif big word on the right relays in place (a fixed noun + a cycling verb) — the column steps only when the word changes, aligned to the current page card's midpoint.

Vertical word-roll cycle
The sentence's last word cycles on a vertical roller, 3 swaps at 0.55s each, fast then very slow with a slight overshoot; neighboring rows carry vertical blur and grayscale by distance, the centered word snapping from gray to accent color as it lands.

Two code reveals, side by side
The same syntax-highlighted code reveals two ways side by side — left: line-level stagger fading up 8px, right: character-by-character typing keeping each token's original color, with a #3a4468 block cursor on the current character.