Motion · Chuyển cảnh

Khối màu nhảy bậc nuốt màn

Hai kiểu khối màu nhảy bậc rời rạc nuốt màn hình — A, thanh nhỏ giữa khung nhảy cứng 3–5 bậc giãn thành toàn màn hình (huy hiệu bật hai nhịp sau khi chiếm lĩnh), B, khối màu từ góc nhảy chéo 3 bậc nuốt màn và mang theo một thẻ trang tiến từng bậc.

1920×108016:930 fps5.06s · 152 frameremotionGiấy phép: Apache-2.0#shotcraft#remotion#transition

Nguồn: video-shotcraft (Vincent Wei) ↗ · Apache-2.0 · Composition Remotion (React/TSX) — có video preview, không có player trong trình duyệt

Khi nào dùng

Chuyển cảnh màu thương hiệu/bàn giao chương; đoạn cảm giác "cứng không easing" kiểu game pixel; sân khấu màu đặc sau khi chiếm lĩnh cho đoạn tiếp theo.

Ý đồ

Các hiệu ứng wipe có sẵn trong thư viện đều là quét liên tục — ranh giới di chuyển đều hoặc theo easing. Thẻ này đi ngược lại: hoàn toàn không nội suy, không easing, khối màu mọc như khối vuông game pixel đời cũ, mỗi bậc nhảy là một cú cắt cứng, giữa các bậc nhảy hoàn toàn đứng yên. Sự khựng lại chính là nhịp điệu: 3–5 tiếng "cạch, cạch, cạch" tuyên bố mạnh hơn bất kỳ cú quét mượt nào. Biến thể B thêm một lớp: khi khối màu tiến lên, nó mang theo một thẻ nội dung nhảy rời rạc cùng bậc — thẻ không tween, đọc thành "cả khối bị chuyển vào", khối màu là xe chở hàng chứ không phải trang trí.

Thời lượng & năng lượng

  • Thời lượng: A ~2.5s (mọc 44f + huy hiệu + giữ) / B ~1.5–2s (3 bậc nhảy 30f + giữ); demo tổng 150f.
  • Năng lượng: Trung bình cao (năng lượng đến từ sự khựng của bước nhảy chứ không phải tốc độ).

Công thức cảnh quay (bản gốc tiếng Trung — timing, easing, bảng tham số, lỗi hay gặp)

意图

库里 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 斜角吞屏)

Mã nguồn tham chiếu (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

Component import fixture chung từ demos/_fixtures và helper từ assets/lib của repo; xem SKILL.md trong repo để biết quy trình render.

Mọi thứ trên trang này đều có bản máy đọc. Đưa agent link JSON, hoặc thêm MCP server gimgs rồi bảo nó tìm motion template.

  1. Tải JSON — trong đó có công thức cảnh quay (timing, easing, bảng tham số, lỗi hay gặp) và toàn bộ source TSX.
  2. Clone repo video-shotcraft; component import fixture chung từ demos/_fixtures và helper từ assets/lib.
  3. Đăng ký component thành <Composition> trong project Remotion rồi render bằng `npx remotion render`, hoặc dựng lại công thức bằng engine của bạn.
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 "Khối màu nhảy bậc nuốt màn" (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.0Mở template gốc ↗
// ===== 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
—

Cùng danh mục