Motion · Transition

Color Block Step Wipe

Two ways a discrete stepped color block swallows the screen — A, a small center bar hard-jumps 3–5 steps to full screen (a badge double-pops once it takes over); B, a block eats the screen diagonally from a corner in 3 jumps, carrying a page card forward one jump at a time.

1920×108016:930 fps5.06s · 152 framesremotionLicense: Apache-2.0#shotcraft#remotion#transition

Source: video-shotcraft (Vincent Wei) ↗ · Apache-2.0 · Remotion composition (React/TSX) — preview video, no in-browser player

When to use

Brand-color transitions/chapter handoffs; "hard, no-easing" pixel-game-feel segments; a solid-color stage to host the next segment after takeover.

Intention

The wipes already in the library are all continuous sweeps — a boundary moving across at a constant or eased rate. This card goes the other way: zero interpolation, zero easing, the whole time — the color block grows like an old-school pixel game block, every jump a hard cut, completely still between jumps. The choppiness is the rhythm: 3–5 "clack, clack, clack" beats announce more than one smooth sweep ever could. Variant B adds another layer: as the block advances, it carries a content card jumping in the same discrete steps — the card doesn't tween, so it reads as "the whole thing got physically moved in," with the color block as cargo carrier, not decoration.

Duration & energy

  • Duration: A ~2.5s (grow 44f + badge + hold) / B ~1.5–2s (3 jumps 30f + hold); demo total 150f.
  • Energy: Medium-high (the energy comes from the punch of the jump, not from speed).

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

意图

库里 wipe 类全是连续扫过——边界匀速或缓动地推过去。本卡反着来: 全程零插值零缓动,色块像老式像素游戏的方块生长,每一跳都是硬切, 跳与跳之间完全静止。顿挫本身就是节奏:3–5 声"咔、咔、咔"比一次 平滑扫过更有宣告感。变体 B 再加一层:色块推进时携带一张内容卡同拍 离散跳位——卡不做补间,读作"整块被搬进来",色块是运货的不是装饰的。

动效核心

  • 核心是 stepVal 帧阈值查表:frame 越过阈值瞬间跳到新值,无插值——

这是本卡的语法宪法,任何一处混进缓动整卡手感就破

  • A 式:宽/高两轴分步跳(demo:w 0→280→820→1340→1920 @ 8f 间隔;

h 先横条后纵向补齐),先长条后铺满——两轴不同步才有"生长"感

  • A 收尾徽章也用阶跃模拟过冲:scale 0→0.55→1.12→1 三跳(52/58/63f)

——同一语法贯穿到底,徽章若用 spring 会显得"来自另一部片"

  • B 式:clipPath polygon 对角线推进量 p 分 3 档硬跳(0→42→106→200,

p=200 全覆盖);携带卡按同一批阈值查表跳位(画外→3 个停靠点)

  • 跳位间隔 6–12f 不等距——等距读作 GIF 掉帧,不等距读作"节拍"

参数表

| 参数 | 典型值 | 调节手感 | |------|--------|----------| | 步数 | A 4–5 跳 / B 3 跳 | ≥7 跳读作低帧率滚动而非阶跃;2 跳读作闪切 | | 跳位间隔 | 6–12f | <5f 眼睛跟不上"跳了几步";>16f 中段静止读作卡死 | | 徽章过冲 | 0.55→1.12→1 三档硬跳 | 改成连续 spring 破语法;过冲档 >1.2 读作弹跳动画 | | 携带卡 | 与色块同拍跳位,rotate -4° 定角 | 卡若做补间滑动,"整块搬运"手感全失;逐跳换角度读作抖动 | | 斜角 clip | polygon 直角三角形从角落长出 | 边缘加圆角/羽化即破"硬边"人设 | | 接管 hold | 铺满后 ≥30f 纯色静置再进下段内容 | 刚铺满就上内容,"吞屏"这一拍没呼吸完 |

已知坑

  • demo 在灰阶/占位素材上调校通过——参数是调校起点非实战定稿,

首次实战须以真实素材回验

  • 与 wipe-transitions 分工:clock-wipe/blinds 是连续几何边界扫过(顺滑系),

本卡是离散阶跃(顿挫系)——同片两系并用要隔开段落,紧邻会互相衬得对方像 bug

  • 与 shot-transitions 的关系:本卡是"转场+接管"复合体(色块留下当新场底色),

纯交接不留场的接缝用 shot-transitions 选型,别为了转场硬造一个色块

  • 声音强依赖:每跳一声打点(同 cel-flash-stomp 的 kick 逻辑)——

无声版阶跃容易被观众读作播放器卡顿

  • 阶跃的"故意感"靠对比成立:同段落其他元素须是顺滑补间,全片到处阶跃

就没人信这是设计

  • 实战品牌色:色块用品牌主色,A/B 两式同片可各一次但换色(demo 蓝/红);

同色连用两次读作素材复用

参考实现

demos/transition/color-block-step-wipe/ (ColorBlockStepWipe.tsx) 原片出处:notion-ai 1.5–3.5s(A 中央阶跃)+ 26–27s(B 斜角吞屏)

Reference implementation (Remotion)

  • demos/transition/color-block-step-wipe/ColorBlockStepWipe.tsx — https://raw.githubusercontent.com/Vincentwei1021/video-shotcraft/main/demos/transition/color-block-step-wipe/ColorBlockStepWipe.tsx

The component imports shared fixtures from demos/_fixtures and helpers from assets/lib in the repo; SKILL.md there documents the render workflow.

Everything on this page is also machine-readable. Point your agent at the JSON, or add the gimgs MCP server and ask it to search motion templates.

  1. Fetch the JSON — it holds the shot recipe (timing, easing, parameter table, pitfalls) and the full TSX source.
  2. Clone the video-shotcraft repo; the component imports shared fixtures from demos/_fixtures and helpers from assets/lib.
  3. Register the component as a <Composition> in a Remotion project and render with `npx remotion render`, or re-implement the recipe in your own engine.
curl -s https://gimgs.net/motion/color-block-step-wipe.json
git clone https://github.com/Vincentwei1021/video-shotcraft
# component: demos/transition/color-block-step-wipe/ColorBlockStepWipe.tsx
npx remotion render <CompositionId> out.mp4
claude mcp add --transport http gimgs https://gimgs.net/mcp
# then: search_motion_templates / get_motion_template("color-block-step-wipe")

Prompt

Use the video-shotcraft shot recipe "Color Block Step Wipe" (Remotion composition, Apache-2.0) published on gimgs.net.
Recipe JSON (prompt = timing/easing/parameter table/pitfalls, files = TSX source): https://gimgs.net/motion/color-block-step-wipe.json
Raw TSX: https://gimgs.net/motion/color-block-step-wipe/template.html
Repository: https://github.com/Vincentwei1021/video-shotcraft  (component: demos/transition/color-block-step-wipe/ColorBlockStepWipe.tsx; imports demos/_fixtures and assets/lib)
Spec: 1920x1080, 30 fps, 5.06s

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,431 chars · Apache-2.0Open raw template ↗
// ===== demos/transition/color-block-step-wipe/ColorBlockStepWipe.tsx =====
// color-block-step-wipe —— 纯色矩形按 steps() 离散阶跃吞屏转场
// 源:notion-ai 1.5–3.5s(蓝块中央阶跃生长)+ 26–27s(红块右下角斜向吃屏,携带页面卡)
// 核心语法:无缓动、逐帧硬跳的块状生长,像素游戏手感。
import React from 'react';
import { AbsoluteFill, useCurrentFrame } from 'remotion';
import { G, Card } from '../../_fixtures/Fixtures';

const BLUE = '#2383e2';
const RED = '#e8503a';

// 离散阶跃:frame 越过阈值瞬间跳到新值,无插值
const stepVal = (frame: number, steps: Array<[number, number]>): number => {
  let v = steps[0][1];
  for (const [f, val] of steps) {
    if (frame >= f) v = val;
  }
  return v;
};

// 蓝底上的圆形 AI 表情徽章
const AiBadge: React.FC<{ scale: number; opacity: number }> = ({ scale, opacity }) => (
  <div
    style={{
      width: 170,
      height: 170,
      borderRadius: '50%',
      background: '#fdf6ec',
      opacity,
      transform: `scale(${scale})`,
      display: 'flex',
      alignItems: 'center',
      justifyContent: 'center',
      boxShadow: '0 6px 24px rgba(0,0,0,0.18)',
    }}
  >
    <svg width={110} height={110} viewBox="0 0 110 110">
      <circle cx={36} cy={44} r={8} fill={G.ink} />
      <circle cx={74} cy={44} r={8} fill={G.ink} />
      <path d="M32 70 Q55 88 78 70" stroke={G.ink} strokeWidth={7} fill="none" strokeLinecap="round" />
      <path d="M24 28 Q34 20 44 26" stroke={G.ink} strokeWidth={6} fill="none" strokeLinecap="round" />
      <path d="M66 26 Q76 20 86 28" stroke={G.ink} strokeWidth={6} fill="none" strokeLinecap="round" />
    </svg>
  </div>
);

// 变体 B 背景:极简灰阶页面(不动 Fixtures,只组合)
const GrayPage: React.FC = () => (
  <AbsoluteFill style={{ background: G.panel, padding: '90px 160px', boxSizing: 'border-box' }}>
    <div style={{ height: 40, width: 560, background: G.bar, borderRadius: 12, marginBottom: 40 }} />
    {[92, 78, 86, 60].map((w, i) => (
      <div key={i} style={{ height: 18, width: `${w}%`, background: G.line, borderRadius: 9, marginBottom: 24 }} />
    ))}
    <div style={{ display: 'flex', gap: 32, marginTop: 30 }}>
      <Card w={420} h={280} seed={2} />
      <Card w={420} h={280} seed={5} />
    </div>
  </AbsoluteFill>
);

export const ColorBlockStepWipe: React.FC = () => {
  const frame = useCurrentFrame();

  // ---------- 场景 A(0–77f):蓝块中央阶跃生长 ----------
  if (frame < 78) {
    // [宽, 高] 逐级硬跳:小条 → 长条 → 半屏色带 → 全屏
    const w = stepVal(frame, [
      [0, 0],
      [8, 280],
      [16, 820],
      [24, 1340],
      [32, 1920],
      [44, 1920],
    ]);
    const h = stepVal(frame, [
      [0, 0],
      [8, 96],
      [16, 96],
      [24, 320],
      [32, 580],
      [44, 1080],
    ]);
    // 徽章:全屏接管后阶跃弹出(同样离散,两跳到位)
    const badgeScale = stepVal(frame, [
      [0, 0],
      [52, 0.55],
      [58, 1.12],
      [63, 1],
    ]);
    const badgeOpacity = frame >= 52 ? 1 : 0;
    return (
      <AbsoluteFill style={{ background: G.bg, alignItems: 'center', justifyContent: 'center' }}>
        <div
          style={{
            position: 'absolute',
            left: 960 - w / 2,
            top: 540 - h / 2,
            width: w,
            height: h,
            background: BLUE,
            display: 'flex',
            alignItems: 'center',
            justifyContent: 'center',
          }}
        />
        <AiBadge scale={badgeScale} opacity={badgeOpacity} />
      </AbsoluteFill>
    );
  }

  // ---------- 场景 B(78–149f):红块从右下角斜向阶跃吃屏,携带灰阶页面卡 ----------
  // p 控制对角线推进量:p=0 无,p=200 全覆盖
  const p = stepVal(frame, [
    [78, 0],
    [84, 42],
    [96, 106],
    [108, 200],
  ]);
  // 卡片随色块逐跳前进(同样离散跳位)
  const cardPos = stepVal(frame, [
    [78, 0],
    [84, 1],
    [96, 2],
    [108, 3],
  ]);
  const cardXY: Array<[number, number]> = [
    [2100, 1180], // 画外
    [1480, 800],
    [980, 560],
    [560, 350],
  ];
  const [cx, cy] = cardXY[cardPos];
  const clip =
    p <= 0
      ? 'polygon(100% 100%, 100% 100%, 100% 100%)'
      : `polygon(${100 - p}% 100%, 100% ${100 - p}%, 100% 100%)`;

  return (
    <AbsoluteFill>
      <GrayPage />
      <AbsoluteFill style={{ background: RED, clipPath: clip }} />
      {p > 0 && (
        <div
          style={{
            position: 'absolute',
            left: cx - 210,
            top: cy - 145,
            transform: 'rotate(-4deg)',
            boxShadow: '0 18px 50px rgba(0,0,0,0.3)',
            borderRadius: 14,
          }}
        >
          <Card w={420} h={290} seed={7} />
        </div>
      )}
    </AbsoluteFill>
  );
};


  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/transition/color-block-step-wipe/ColorBlockStepWipe.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
—

More in this category