Motion · Câmera

Crash Zoom Punch

A wide shot crash-zooms to a target close-up in one beat (6f), landing either with a bounce overshoot (elastic) or a hard stop with screen shake (weighty).

1920×108016:930 fps4.05s · 122 quadrosremotionLicença: Apache-2.0#shotcraft#remotion#camera#effects

Fonte: video-shotcraft (Vincent Wei) ↗ · Apache-2.0 · Composição Remotion (React/TSX) — vídeo de prévia, sem player no navegador

When to use

A "calling out" shot for feature segments — snapping the viewer's eye onto a target card/module in one beat; use the hard-stop version for emphasis.

Intention

A slow push-in (spotlight-hero-card) says "please look"; a crash zoom says "look at this!" — going from wide to close-up in a single beat leaves the eye no choice. The landing has two textures to pick from: a bounce-back is elastic ("look at this"), a hard stop with screen shake is weighty ("this is it") — choose by emphasis level.

Duration & energy

  • Duration: About 0.5s of motion plus hold before/after (motion 6–11f, pre-hold ≥30f to establish the wide shot, post-hold ≥45f to read the close-up).
  • Energy: High (instantaneous impact, not sustained high energy).

Shot recipe (original Chinese — timing, easing, parameter table, known pitfalls)

意图

慢推近(spotlight-hero-card)是"请看",急推是"看这个!"——一拍之内 从全景砸到特写,视线没有选择余地。落位质感分两款:回弹是弹性 ("看这个"),撞停震屏是重量("就是它"),按强调级选。

动效核心

  • zoom 6f ease-in 急加速(如 1→2.6),cx/cy 同步 ease-in 收敛到目标中心
  • 回弹款:zoom 过冲后 5f 回收 3–6%(2.6→2.45)
  • 撞停款:到位帧起机位高频抖 + 指数衰减(amp 14px、τ≈1.8f、6f 收干),

不回弹

  • <CameraMotionBlur shutterAngle={200} samples={20}> 只包急推段

(撞停震屏段保持清晰抖动);采样按"回波间距 ≤ 字高"配(轮 A 判例)

参数表

| 参数 | 典型值 | 调节手感 | |------|--------|----------| | 急推时长 | 6f(4–8f) | >10f 读作普通推近,冲击感消失 | | 目标 zoom | 2.4–2.8 | 终点构图以目标卡占画面 60–75% 为准 | | 回弹幅度 | zoom 的 3–6% | 过大读作弹簧玩具 | | 震屏包络 | 14px·e^(−t/1.8) | 幅度须过肉眼阈值(可感性判例),>20px 读作故障 |

已知坑

  • 终点必须是高清纹理槽位(card4-hires 级)——急推后全程特写它,

低倍截图糊字(Q2);终点先按 Q2 的高分辨率栅格化技法处理

  • 两款别混用:回弹后再震屏读作穿帮;一支片急推 ≤2 次(P4 手法去重精神)
  • 参数经占位素材调校转正,非实战定稿,首次实战后回验

参考实现

demos/camera/crash-zoom-punch/ (CrashImpactReal.tsx / CrashZoomReal.tsx)

Reference implementation (Remotion)

  • demos/camera/crash-zoom-punch/CrashImpactReal.tsx — https://raw.githubusercontent.com/Vincentwei1021/video-shotcraft/main/demos/camera/crash-zoom-punch/CrashImpactReal.tsx
  • demos/camera/crash-zoom-punch/CrashZoomReal.tsx — https://raw.githubusercontent.com/Vincentwei1021/video-shotcraft/main/demos/camera/crash-zoom-punch/CrashZoomReal.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.

  1. Baixe o JSON — contém a receita do plano (timing, easing, tabela de parâmetros, armadilhas) e o código TSX completo.
  2. Clone o repositório video-shotcraft; o componente importa fixtures de demos/_fixtures e helpers de assets/lib.
  3. 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/crash-zoom-punch.json
git clone https://github.com/Vincentwei1021/video-shotcraft
# component: demos/camera/crash-zoom-punch/CrashImpactReal.tsx, demos/camera/crash-zoom-punch/CrashZoomReal.tsx
npx remotion render <CompositionId> out.mp4
claude mcp add --transport http gimgs https://gimgs.net/mcp
# then: search_motion_templates / get_motion_template("crash-zoom-punch")

Prompt

Use the video-shotcraft shot recipe "Crash Zoom Punch" (Remotion composition, Apache-2.0) published on gimgs.net.
Recipe JSON (prompt = timing/easing/parameter table/pitfalls, files = TSX source): https://gimgs.net/motion/crash-zoom-punch.json
Raw TSX: https://gimgs.net/motion/crash-zoom-punch/template.html
Repository: https://github.com/Vincentwei1021/video-shotcraft  (component: demos/camera/crash-zoom-punch/CrashImpactReal.tsx, demos/camera/crash-zoom-punch/CrashZoomReal.tsx; imports demos/_fixtures and assets/lib)
Spec: 1920x1080, 30 fps, 4.05s

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).

JSON · Markdown · llms.txt

4,651 chars · Apache-2.0Abrir template bruto ↗
// ===== demos/camera/crash-zoom-punch/CrashImpactReal.tsx =====
// crash-impact 急推撞停——同 crash-zoom 的急推,到位瞬间不回弹而是
// 撞停震屏:高频抖 + 指数衰减 6f,然后真静止。对比点:重量感 vs 弹性感。
import { AbsoluteFill, Img, interpolate, staticFile, useCurrentFrame, Easing } from 'remotion';
import { CameraMotionBlur } from '@remotion/motion-blur';
import layout from '../../_textures/live-layout.json';

export const CRASHIMPACT_DUR = 120;

const TARGET = { cx: 960, cy: 772 };
const VIEW_Y = 180;
const HIT = 46;

const Scene: React.FC = () => {
  const frame = useCurrentFrame();
  const zoom = interpolate(frame, [40, HIT], [1, 2.5], {
    extrapolateLeft: 'clamp', extrapolateRight: 'clamp',
    easing: Easing.bezier(0.55, 0, 0.7, 1),
  });
  const cx = interpolate(frame, [40, HIT], [960, TARGET.cx], {
    extrapolateLeft: 'clamp', extrapolateRight: 'clamp', easing: Easing.in(Easing.quad),
  });
  const cy = interpolate(frame, [40, HIT], [VIEW_Y + 540, TARGET.cy], {
    extrapolateLeft: 'clamp', extrapolateRight: 'clamp', easing: Easing.in(Easing.quad),
  });
  // 撞停震屏:amp 14px 指数衰减 ~6f 收干(可感幅度,参考轮 #2 可感档)
  const since = frame - HIT;
  const env = since >= 0 ? 14 * Math.exp(-since / 1.8) : 0;
  const sx = env * Math.sin(since * 3.3);
  const sy = env * 0.7 * Math.sin(since * 4.1 + 0.9);
  return (
    <AbsoluteFill style={{ backgroundColor: '#f9f6f1', overflow: 'hidden' }}>
      <div
        style={{
          position: 'absolute', width: 1920, height: layout.projects.pageH,
          transform: `translate(${960 - cx * zoom + sx}px, ${540 - cy * zoom + sy}px) scale(${zoom})`,
          transformOrigin: '0 0',
        }}
      >
        <Img src={staticFile('textures/live/projects-full.png')} style={{ position: 'absolute', width: 1920 }} />
        <Img
          src={staticFile('textures/live/card4-hires.png')}
          style={{
            position: 'absolute',
            left: layout.projects.cards[3].x, top: layout.projects.cards[3].y,
            width: layout.projects.cards[3].w, height: layout.projects.cards[3].h,
          }}
        />
      </div>
    </AbsoluteFill>
  );
};

export const CrashImpactReal: React.FC = () => {
  const frame = useCurrentFrame();
  // blur 只包急推段;撞停震屏段保持清晰抖动
  return frame >= 38 && frame <= HIT ? (
    <CameraMotionBlur shutterAngle={200} samples={20}>
      <Scene />
    </CameraMotionBlur>
  ) : (
    <Scene />
  );
};


// ===== demos/camera/crash-zoom-punch/CrashZoomReal.tsx =====
// crash-zoom 急推——真实 projects 页全景一拍推到 card4(高清纹理槽位)。
// 节拍:0–40 全景 hold → 40–46 急推 6f(ease-in,峰值放大 2.6x)→
// 46–51 过冲回弹(2.6→2.45)→ 51–120 特写 hold 真静止。
// blur 只包 40–46 急推段(轮 A 规律:极速段 samples 20)。
import { AbsoluteFill, Img, interpolate, staticFile, useCurrentFrame, Easing } from 'remotion';
import { CameraMotionBlur } from '@remotion/motion-blur';
import layout from '../../_textures/live-layout.json';

export const CRASHZOOM_DUR = 120;

// card4 中心(页面空间):x=781+357/2≈960, y=616+312/2=772
const TARGET = { cx: 960, cy: 772 };
const VIEW_Y = 180; // 全景观察窗顶(页面 y)

const Scene: React.FC = () => {
  const frame = useCurrentFrame();
  const zoom = interpolate(frame, [40, 46, 51], [1, 2.6, 2.45], {
    extrapolateLeft: 'clamp', extrapolateRight: 'clamp',
    easing: Easing.bezier(0.55, 0, 0.7, 1),
  });
  const cx = interpolate(frame, [40, 46], [960, TARGET.cx], {
    extrapolateLeft: 'clamp', extrapolateRight: 'clamp', easing: Easing.in(Easing.quad),
  });
  const cy = interpolate(frame, [40, 46], [VIEW_Y + 540, TARGET.cy], {
    extrapolateLeft: 'clamp', extrapolateRight: 'clamp', easing: Easing.in(Easing.quad),
  });
  return (
    <AbsoluteFill style={{ backgroundColor: '#f9f6f1', overflow: 'hidden' }}>
      <div
        style={{
          position: 'absolute', width: 1920, height: layout.projects.pageH,
          transform: `translate(${960 - cx * zoom}px, ${540 - cy * zoom}px) scale(${zoom})`,
          transformOrigin: '0 0',
        }}
      >
        <Img src={staticFile('textures/live/projects-full.png')} style={{ position: 'absolute', width: 1920 }} />
        {/* 高清目标卡覆盖原位,放大后文字仍锐(Q2) */}
        <Img
          src={staticFile('textures/live/card4-hires.png')}
          style={{
            position: 'absolute',
            left: layout.projects.cards[3].x, top: layout.projects.cards[3].y,
            width: layout.projects.cards[3].w, height: layout.projects.cards[3].h,
          }}
        />
      </div>
    </AbsoluteFill>
  );
};

export const CrashZoomReal: React.FC = () => {
  const frame = useCurrentFrame();
  return frame >= 38 && frame <= 48 ? (
    <CameraMotionBlur shutterAngle={200} samples={20}>
      <Scene />
    </CameraMotionBlur>
  ) : (
    <Scene />
  );
};


  1. Read the recipe
    Prompt = when to use, intention, parameter table with typical values and how each one feels, known pitfalls. Treat values as calibrated starting points.
  2. Get the code
    tool: git
    git clone https://github.com/Vincentwei1021/video-shotcraft && cd video-shotcraft && npm install
  3. Register + render
    tool: remotion
    npx remotion render <CompositionId> out.mp4 # component: demos/camera/crash-zoom-punch/CrashImpactReal.tsx, demos/camera/crash-zoom-punch/CrashZoomReal.tsx
  4. Or re-implement
    Port the timing/easing from the recipe to HTML + WAAPI (gimgs motion contract) or any engine; keep the same segment windows and easing.
paramtypedefaultdescription
—

Mais nesta categoria