{
  "slug": "color-block-step-wipe",
  "title": "Color Block Step Wipe",
  "tagline": "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.",
  "description": "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 ove",
  "category": "transition",
  "tags": [
    "shotcraft",
    "remotion",
    "transition"
  ],
  "tier": "free",
  "license": "Apache-2.0",
  "spec": {
    "width": 1920,
    "height": 1080,
    "fps": 30,
    "duration": 5.06,
    "aspect": "16:9"
  },
  "kind": "remotion",
  "params_schema": {
    "type": "object",
    "properties": {}
  },
  "default_params": {},
  "preview": {
    "poster": "https://gimgs.net/motion/media/color-block-step-wipe/poster-a40a0ca9e65e.jpg",
    "video": "https://gimgs.net/motion/media/color-block-step-wipe/video-25d95987cd96.mp4"
  },
  "variants": [
    {
      "key": "color-block-step-wipe",
      "label": "color-block-step-wipe",
      "description": "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.",
      "use": "",
      "video": "https://gimgs.net/motion/media/color-block-step-wipe/video-25d95987cd96.mp4",
      "poster": "https://gimgs.net/motion/media/color-block-step-wipe/poster-a40a0ca9e65e.jpg"
    }
  ],
  "credits": {
    "author": "video-shotcraft (Vincent Wei)",
    "url": "https://github.com/Vincentwei1021/video-shotcraft"
  },
  "page_url": "https://gimgs.net/motion/color-block-step-wipe.html",
  "json_url": "https://gimgs.net/motion/color-block-step-wipe.json",
  "template_url": "https://gimgs.net/motion/color-block-step-wipe/template.html",
  "play_url": null,
  "markdown_url": "https://gimgs.net/motion/color-block-step-wipe.md",
  "updated_at": "2026-09-24T07:39:51.147Z",
  "prompt": "## When to use\n\nBrand-color transitions/chapter handoffs; \"hard, no-easing\" pixel-game-feel segments; a solid-color stage to host the next segment after takeover.\n\n## Intention\n\nThe 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.\n\n## Duration & energy\n\n- Duration: A ~2.5s (grow 44f + badge + hold) / B ~1.5–2s (3 jumps 30f + hold); demo total 150f.\n- Energy: Medium-high (the energy comes from the punch of the jump, not from speed).\n\n## Shot recipe (original Chinese — timing, easing, parameter table, known pitfalls)\n\n## 意图\n库里 wipe 类全是连续扫过——边界匀速或缓动地推过去。本卡反着来：\n**全程零插值零缓动**，色块像老式像素游戏的方块生长，每一跳都是硬切，\n跳与跳之间完全静止。顿挫本身就是节奏：3–5 声\"咔、咔、咔\"比一次\n平滑扫过更有宣告感。变体 B 再加一层：色块推进时携带一张内容卡同拍\n离散跳位——卡不做补间，读作\"整块被搬进来\"，色块是运货的不是装饰的。\n\n## 动效核心\n- 核心是 stepVal 帧阈值查表：frame 越过阈值瞬间跳到新值，无插值——\n  这是本卡的语法宪法，任何一处混进缓动整卡手感就破\n- A 式：宽/高两轴分步跳（demo：w 0→280→820→1340→1920 @ 8f 间隔；\n  h 先横条后纵向补齐），先长条后铺满——两轴不同步才有\"生长\"感\n- A 收尾徽章也用阶跃模拟过冲：scale 0→0.55→1.12→1 三跳（52/58/63f）\n  ——同一语法贯穿到底，徽章若用 spring 会显得\"来自另一部片\"\n- B 式：clipPath polygon 对角线推进量 p 分 3 档硬跳（0→42→106→200，\n  p=200 全覆盖）；携带卡按同一批阈值查表跳位（画外→3 个停靠点）\n- 跳位间隔 6–12f 不等距——等距读作 GIF 掉帧，不等距读作\"节拍\"\n\n## 参数表\n| 参数 | 典型值 | 调节手感 |\n|------|--------|----------|\n| 步数 | A 4–5 跳 / B 3 跳 | ≥7 跳读作低帧率滚动而非阶跃；2 跳读作闪切 |\n| 跳位间隔 | 6–12f | <5f 眼睛跟不上\"跳了几步\"；>16f 中段静止读作卡死 |\n| 徽章过冲 | 0.55→1.12→1 三档硬跳 | 改成连续 spring 破语法；过冲档 >1.2 读作弹跳动画 |\n| 携带卡 | 与色块同拍跳位，rotate -4° 定角 | 卡若做补间滑动，\"整块搬运\"手感全失；逐跳换角度读作抖动 |\n| 斜角 clip | polygon 直角三角形从角落长出 | 边缘加圆角/羽化即破\"硬边\"人设 |\n| 接管 hold | 铺满后 ≥30f 纯色静置再进下段内容 | 刚铺满就上内容，\"吞屏\"这一拍没呼吸完 |\n\n## 已知坑\n- demo 在灰阶/占位素材上调校通过——参数是调校起点非实战定稿，\n  首次实战须以真实素材回验\n- 与 wipe-transitions 分工：clock-wipe/blinds 是连续几何边界扫过（顺滑系），\n  本卡是离散阶跃（顿挫系）——同片两系并用要隔开段落，紧邻会互相衬得对方像 bug\n- 与 shot-transitions 的关系：本卡是\"转场+接管\"复合体（色块留下当新场底色），\n  纯交接不留场的接缝用 shot-transitions 选型，别为了转场硬造一个色块\n- **声音强依赖**：每跳一声打点（同 cel-flash-stomp 的 kick 逻辑）——\n  无声版阶跃容易被观众读作播放器卡顿\n- 阶跃的\"故意感\"靠对比成立：同段落其他元素须是顺滑补间，全片到处阶跃\n  就没人信这是设计\n- 实战品牌色：色块用品牌主色，A/B 两式同片可各一次但换色（demo 蓝/红）；\n  同色连用两次读作素材复用\n\n## 参考实现\ndemos/transition/color-block-step-wipe/\n（ColorBlockStepWipe.tsx）\n原片出处：notion-ai 1.5–3.5s（A 中央阶跃）+ 26–27s（B 斜角吞屏）\n\n## Reference implementation (Remotion)\n\n- demos/transition/color-block-step-wipe/ColorBlockStepWipe.tsx — https://raw.githubusercontent.com/Vincentwei1021/video-shotcraft/main/demos/transition/color-block-step-wipe/ColorBlockStepWipe.tsx\n\nThe component imports shared fixtures from `demos/_fixtures` and helpers from `assets/lib` in the repo; SKILL.md there documents the render workflow.\n",
  "flow": [
    {
      "step": "Read the recipe",
      "note": "Prompt = when to use, intention, parameter table with typical values and how each one feels, known pitfalls. Treat values as calibrated starting points."
    },
    {
      "step": "Get the code",
      "tool": "git",
      "cmd": "git clone https://github.com/Vincentwei1021/video-shotcraft && cd video-shotcraft && npm install"
    },
    {
      "step": "Register + render",
      "tool": "remotion",
      "cmd": "npx remotion render <CompositionId> out.mp4   # component: demos/transition/color-block-step-wipe/ColorBlockStepWipe.tsx"
    },
    {
      "step": "Or re-implement",
      "note": "Port the timing/easing from the recipe to HTML + WAAPI (gimgs motion contract) or any engine; keep the same segment windows and easing."
    }
  ],
  "files": [
    {
      "path": "demos/transition/color-block-step-wipe/ColorBlockStepWipe.tsx",
      "url": "https://raw.githubusercontent.com/Vincentwei1021/video-shotcraft/main/demos/transition/color-block-step-wipe/ColorBlockStepWipe.tsx"
    }
  ],
  "contract": "React/Remotion composition (TSX) from the open-source video-shotcraft library (Apache-2.0). It is not a browser-playable template: clone the repo, register the component in a Remotion project and render with `npx remotion render`. The recipe (prompt) describes timing, easing and parameters so you can also re-implement the shot in any engine.",
  "render": {
    "engine": "remotion",
    "frames": 152,
    "repo": "https://github.com/Vincentwei1021/video-shotcraft",
    "files": [
      "https://raw.githubusercontent.com/Vincentwei1021/video-shotcraft/main/demos/transition/color-block-step-wipe/ColorBlockStepWipe.tsx"
    ],
    "note": "Clone https://github.com/Vincentwei1021/video-shotcraft (npm install). The component lives under demos/{category}/{name}/ and imports shared fixtures from demos/_fixtures and helpers from assets/lib. Copy it (with those imports) into a Remotion project, register a <Composition> with the template's width/height/fps/duration in Root.tsx, then `npx remotion render <CompositionId> out.mp4`. SKILL.md in the repo documents the full Claude Code / Codex workflow. The prompt below is the shot recipe (timing, easing, parameter table, pitfalls) — enough to re-implement the shot in HTML/WAAPI or another engine if you prefer."
  },
  "source": "// ===== demos/transition/color-block-step-wipe/ColorBlockStepWipe.tsx =====\n// color-block-step-wipe —— 纯色矩形按 steps() 离散阶跃吞屏转场\n// 源：notion-ai 1.5–3.5s（蓝块中央阶跃生长）+ 26–27s（红块右下角斜向吃屏，携带页面卡）\n// 核心语法：无缓动、逐帧硬跳的块状生长，像素游戏手感。\nimport React from 'react';\nimport { AbsoluteFill, useCurrentFrame } from 'remotion';\nimport { G, Card } from '../../_fixtures/Fixtures';\n\nconst BLUE = '#2383e2';\nconst RED = '#e8503a';\n\n// 离散阶跃：frame 越过阈值瞬间跳到新值，无插值\nconst stepVal = (frame: number, steps: Array<[number, number]>): number => {\n  let v = steps[0][1];\n  for (const [f, val] of steps) {\n    if (frame >= f) v = val;\n  }\n  return v;\n};\n\n// 蓝底上的圆形 AI 表情徽章\nconst AiBadge: React.FC<{ scale: number; opacity: number }> = ({ scale, opacity }) => (\n  <div\n    style={{\n      width: 170,\n      height: 170,\n      borderRadius: '50%',\n      background: '#fdf6ec',\n      opacity,\n      transform: `scale(${scale})`,\n      display: 'flex',\n      alignItems: 'center',\n      justifyContent: 'center',\n      boxShadow: '0 6px 24px rgba(0,0,0,0.18)',\n    }}\n  >\n    <svg width={110} height={110} viewBox=\"0 0 110 110\">\n      <circle cx={36} cy={44} r={8} fill={G.ink} />\n      <circle cx={74} cy={44} r={8} fill={G.ink} />\n      <path d=\"M32 70 Q55 88 78 70\" stroke={G.ink} strokeWidth={7} fill=\"none\" strokeLinecap=\"round\" />\n      <path d=\"M24 28 Q34 20 44 26\" stroke={G.ink} strokeWidth={6} fill=\"none\" strokeLinecap=\"round\" />\n      <path d=\"M66 26 Q76 20 86 28\" stroke={G.ink} strokeWidth={6} fill=\"none\" strokeLinecap=\"round\" />\n    </svg>\n  </div>\n);\n\n// 变体 B 背景：极简灰阶页面（不动 Fixtures，只组合）\nconst GrayPage: React.FC = () => (\n  <AbsoluteFill style={{ background: G.panel, padding: '90px 160px', boxSizing: 'border-box' }}>\n    <div style={{ height: 40, width: 560, background: G.bar, borderRadius: 12, marginBottom: 40 }} />\n    {[92, 78, 86, 60].map((w, i) => (\n      <div key={i} style={{ height: 18, width: `${w}%`, background: G.line, borderRadius: 9, marginBottom: 24 }} />\n    ))}\n    <div style={{ display: 'flex', gap: 32, marginTop: 30 }}>\n      <Card w={420} h={280} seed={2} />\n      <Card w={420} h={280} seed={5} />\n    </div>\n  </AbsoluteFill>\n);\n\nexport const ColorBlockStepWipe: React.FC = () => {\n  const frame = useCurrentFrame();\n\n  // ---------- 场景 A（0–77f）：蓝块中央阶跃生长 ----------\n  if (frame < 78) {\n    // [宽, 高] 逐级硬跳：小条 → 长条 → 半屏色带 → 全屏\n    const w = stepVal(frame, [\n      [0, 0],\n      [8, 280],\n      [16, 820],\n      [24, 1340],\n      [32, 1920],\n      [44, 1920],\n    ]);\n    const h = stepVal(frame, [\n      [0, 0],\n      [8, 96],\n      [16, 96],\n      [24, 320],\n      [32, 580],\n      [44, 1080],\n    ]);\n    // 徽章：全屏接管后阶跃弹出（同样离散，两跳到位）\n    const badgeScale = stepVal(frame, [\n      [0, 0],\n      [52, 0.55],\n      [58, 1.12],\n      [63, 1],\n    ]);\n    const badgeOpacity = frame >= 52 ? 1 : 0;\n    return (\n      <AbsoluteFill style={{ background: G.bg, alignItems: 'center', justifyContent: 'center' }}>\n        <div\n          style={{\n            position: 'absolute',\n            left: 960 - w / 2,\n            top: 540 - h / 2,\n            width: w,\n            height: h,\n            background: BLUE,\n            display: 'flex',\n            alignItems: 'center',\n            justifyContent: 'center',\n          }}\n        />\n        <AiBadge scale={badgeScale} opacity={badgeOpacity} />\n      </AbsoluteFill>\n    );\n  }\n\n  // ---------- 场景 B（78–149f）：红块从右下角斜向阶跃吃屏，携带灰阶页面卡 ----------\n  // p 控制对角线推进量：p=0 无，p=200 全覆盖\n  const p = stepVal(frame, [\n    [78, 0],\n    [84, 42],\n    [96, 106],\n    [108, 200],\n  ]);\n  // 卡片随色块逐跳前进（同样离散跳位）\n  const cardPos = stepVal(frame, [\n    [78, 0],\n    [84, 1],\n    [96, 2],\n    [108, 3],\n  ]);\n  const cardXY: Array<[number, number]> = [\n    [2100, 1180], // 画外\n    [1480, 800],\n    [980, 560],\n    [560, 350],\n  ];\n  const [cx, cy] = cardXY[cardPos];\n  const clip =\n    p <= 0\n      ? 'polygon(100% 100%, 100% 100%, 100% 100%)'\n      : `polygon(${100 - p}% 100%, 100% ${100 - p}%, 100% 100%)`;\n\n  return (\n    <AbsoluteFill>\n      <GrayPage />\n      <AbsoluteFill style={{ background: RED, clipPath: clip }} />\n      {p > 0 && (\n        <div\n          style={{\n            position: 'absolute',\n            left: cx - 210,\n            top: cy - 145,\n            transform: 'rotate(-4deg)',\n            boxShadow: '0 18px 50px rgba(0,0,0,0.3)',\n            borderRadius: 14,\n          }}\n        >\n          <Card w={420} h={290} seed={7} />\n        </div>\n      )}\n    </AbsoluteFill>\n  );\n};\n\n\n"
}