Motion · Chuyển cảnh
Đẩy chồng lớp từ đáy
Đổi chương bằng cách đẩy từ mép dưới — cảnh mới cả nền lẫn nội dung đẩy nguyên khối từ đáy lên, hất vật lý cảnh cũ ra khỏi khung hình; mỗi chương một màu nền bão hòa riêng.
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
Khung xương đổi chương cho phim sản phẩm nhiều chương (mỗi chương một điểm bán, một màu nền); đoạn cần "nhịp lật trang" xuyên suốt phim.
Ý đồ
wipe-transitions là một đường biên quét qua, trang cũ mới đều đứng yên; page-turn là lật khối hộp. Thẻ này là tính vật lý thứ ba: chương mới hất chương cũ ra ngoài — hai màn hình tiếp xúc cứng, dịch chuyển cùng tốc độ cùng hướng, như máy bán hàng tự động dồn hàng. Điểm then chốt là "cả nền đi nguyên khối": nền + thẻ cửa sổ + dải trang trí hàn thành một khối liền đẩy vào từ mép dưới, người xem đọc được "đổi cả thế giới" chứ không phải "đổi một cái thẻ". Ease-out nặng (nhanh rồi dừng gấp) tạo cảm giác "uỵch" khi vào vị trí; bóng đổ 40px ở mép trên là bằng chứng tiếp xúc vật lý giữa hai màn hình. Đẩy liên tiếp ba chương với độ bão hòa kịch trần, bản thân việc đổi chương trở thành máy đếm nhịp của cả phim — phim slack gốc dựng cả khung xương chỉ bằng chiêu này.
Thời lượng & năng lượng
- Thời lượng: Một lần đẩy vào 30f + giữ trong chương ~1s; demo đẩy liên tiếp ba lần 140f (~4.7s).
- Năng lượng: Trung bình
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-transitions 是一条边界扫过、新旧页都不动;page-turn 是立方体 翻转。本卡是第三种物性:新章把旧章顶出去——两屏刚性接触、同速 同向位移,像自动售货机压栈。命门是"连底色整屏走":底色+窗口卡+装饰 条焊成一块整料从底边推入,观众读到"换了个世界"而不是"换了张卡"。 重 ease-out(快进慢停)给推入一个"哐"的落位感;上缘 40px 接缝阴影 是两屏物理接触的证据。连推三章且底色饱和度拉满,换章本身就成了全片 的节拍器——slack 原片全片就靠这一招做骨架。
动效核心
- 每章一个整屏层:
translateY从 +1080 推到 0,旧章同步被顶到
−1080——两层位移严格同步同缓动,任何速差都读作"滑动穿模"
- 推入缓动 = 重 ease-out
cubic-bezier(0.12, 0.9, 0.2, 1)(快进
慢停),30f 完成;第 i 章的 y = (1−自己推入进度)×H − 下一章推入 进度×H,一条式子管进也管出
- 新章上缘带 40px 渐变接缝阴影(黑 0.30→透明,压在旧章上),落定
后归零——"顶出"的物理接触感全靠它
- 三章底色绿 #2bac76 / 蓝 #36c5f0 / 粉 #e01e5a(demo 取 slack 系
饱和色);每章中央钉一张灰阶窗口卡 + 白色半透明装饰条
- 推入间隔 hold ~1s(demo 18/55/92f 起推);出画的层及时卸载
参数表
| 参数 | 典型值 | 调节手感 | |------|--------|----------| | 推入时长 | 30f,重 ease-out | <20f 读作闪切;线性匀速读作卷帘门,"哐"感全无 | | 章间 hold | ~37f(1.2s 左右) | 章内是内容表演区,<25f 观众没看清就被顶走 | | 接缝阴影 | 上缘 40px,黑 0.30 渐变 | 去掉后两屏像叠影滑动;>80px 读作新章自带黑边 | | 底色 | 每章一种饱和色,相邻章色相拉开 | 相邻章同色系则"换章"读作"微调";灰阶章只能当第 0 章 | | 内容钉死 | 窗口卡/装饰条用章内绝对坐标 | 内容若相对视口定位就会"漂"在推入动画上,穿帮 | | 连推次数 | 2–4 章 | 1 次不成节奏;>4 次观众开始数底色,疲劳 |
已知坑
- demo 在灰阶/占位素材上调校通过——参数是调校起点非实战定稿,
首次实战须以真实素材回验
- 与 wipe-transitions 分工:那卡新旧页都不动、一条几何边界扫过交接
(中性、哪儿都能用);本卡两页都在动、刚性顶出(有物性、自带章节 节奏)——单次接缝用那卡,全片骨架用本卡
- 与 shot-transitions 六式同层选型:本卡能量中档、方向固定向上,
需要能量落差大的接缝(如进 outro)让位给流白/黑场
- 方向统一是骨架感的来源:全片所有章都从底边推,中途换成左推/顶推
节拍器就散了——要变方向就别当骨架用
- 推入进行中两章同屏,都是满屏层——章内动画(卡片入场等)避开推入
的 30f 窗口,不然两章都在动,视线没有锚点
- 实战底色用品牌色板的饱和档;底色饱和度不足时窗口卡"钉在色底上"
的从属关系读不出来,会退化成"卡片各自换背景"
参考实现
demos/transition/bottom-push-stack-wipe/ (BottomPushStackWipe.tsx) 原片出处:slack-promo 22–27s
Mã nguồn tham chiếu (Remotion)
- demos/transition/bottom-push-stack-wipe/BottomPushStackWipe.tsx — https://raw.githubusercontent.com/Vincentwei1021/video-shotcraft/main/demos/transition/bottom-push-stack-wipe/BottomPushStackWipe.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.
- 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.
- Clone repo video-shotcraft; component import fixture chung từ demos/_fixtures và helper từ assets/lib.
- Đă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/bottom-push-stack-wipe.jsongit clone https://github.com/Vincentwei1021/video-shotcraft
# component: demos/transition/bottom-push-stack-wipe/BottomPushStackWipe.tsx
npx remotion render <CompositionId> out.mp4claude mcp add --transport http gimgs https://gimgs.net/mcp
# then: search_motion_templates / get_motion_template("bottom-push-stack-wipe")Prompt
Use the video-shotcraft shot recipe "Đẩy chồng lớp từ đáy" (Remotion composition, Apache-2.0) published on gimgs.net. Recipe JSON (prompt = timing/easing/parameter table/pitfalls, files = TSX source): https://gimgs.net/motion/bottom-push-stack-wipe.json Raw TSX: https://gimgs.net/motion/bottom-push-stack-wipe/template.html Repository: https://github.com/Vincentwei1021/video-shotcraft (component: demos/transition/bottom-push-stack-wipe/BottomPushStackWipe.tsx; imports demos/_fixtures and assets/lib) Spec: 1920x1080, 30 fps, 4.72s 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/transition/bottom-push-stack-wipe/BottomPushStackWipe.tsx =====
// bottom-push-stack-wipe —— slack-promo 22–27s
// 换章手法:新场景连底色整屏从底边向上推入,把旧场景顶出画外,
// 连推三章(三种饱和底色,每章中央钉一张灰阶窗口卡随底色走)。
// 推入用重 ease-out(快进慢停)。
import React from 'react';
import { AbsoluteFill, useCurrentFrame, interpolate, Easing } from 'remotion';
import { Card, G } from '../../_fixtures/Fixtures';
const H = 1080;
// 章节定义:底色 + 卡片种子。第 0 章是起始灰阶场景。
const CHAPTERS = [
{ color: G.bg, label: 0 },
{ color: '#2bac76', label: 1 }, // 绿
{ color: '#36c5f0', label: 2 }, // 蓝
{ color: '#e01e5a', label: 3 }, // 粉红
];
// 每章推入的起始帧;约 32 帧完成一次推入,随后 hold
const PUSH_STARTS = [18, 55, 92];
const PUSH_DUR = 30;
const heavyEaseOut = Easing.bezier(0.12, 0.9, 0.2, 1); // 快进慢停
const ChapterScene: React.FC<{ chapter: number }> = ({ chapter }) => {
const c = CHAPTERS[chapter];
return (
<AbsoluteFill style={{ background: c.color, justifyContent: 'center', alignItems: 'center' }}>
{/* 底色上的淡装饰条,让"底色也在动"更可读 */}
{chapter > 0 && (
<>
<div style={{ position: 'absolute', top: 90, left: 120, width: 500, height: 26, borderRadius: 13, background: 'rgba(255,255,255,0.28)' }} />
<div style={{ position: 'absolute', bottom: 110, right: 140, width: 340, height: 26, borderRadius: 13, background: 'rgba(255,255,255,0.22)' }} />
<div style={{ position: 'absolute', top: 160, right: 220, width: 90, height: 90, borderRadius: '50%', background: 'rgba(255,255,255,0.18)' }} />
</>
)}
{/* 中央钉住的灰阶窗口卡 */}
<div style={{ boxShadow: '0 30px 80px rgba(0,0,0,0.28)', borderRadius: 18 }}>
<div style={{ width: 860, background: '#f2f2f0', borderRadius: '18px 18px 0 0', height: 52, display: 'flex', alignItems: 'center', gap: 10, padding: '0 22px', boxSizing: 'border-box', border: `2px solid ${G.border}`, borderBottom: 'none' }}>
{['#e0605a', '#e8b93e', '#67bb5a'].map((dot, i) => (
<div key={i} style={{ width: 16, height: 16, borderRadius: 8, background: dot }} />
))}
<div style={{ marginLeft: 18, height: 14, width: 220, background: G.bar, borderRadius: 7 }} />
</div>
<Card w={860} h={430} seed={chapter + 2} style={{ borderRadius: '0 0 18px 18px', padding: 34 }} />
</div>
</AbsoluteFill>
);
};
export const BottomPushStackWipe: React.FC = () => {
const frame = useCurrentFrame();
// 每章的推入进度
const progress = PUSH_STARTS.map((s) =>
interpolate(frame, [s, s + PUSH_DUR], [0, 1], {
extrapolateLeft: 'clamp', extrapolateRight: 'clamp', easing: heavyEaseOut,
})
);
return (
<AbsoluteFill style={{ overflow: 'hidden', background: G.bg }}>
{CHAPTERS.map((_, i) => {
// 第 i 章的位移 = 自己被推入的进度 + 被后续章顶出的进度
const pushedIn = i === 0 ? 1 : progress[i - 1]; // 自己进入
const pushedOut = i < CHAPTERS.length - 1 ? progress[i] : 0; // 被下一章顶出
const y = (1 - pushedIn) * H - pushedOut * H;
if (y <= -H || y >= H) return null;
return (
<AbsoluteFill key={i} style={{ transform: `translateY(${y}px)` }}>
<ChapterScene chapter={i} />
{/* 推入时上缘接缝阴影,强化"顶出"的物理感 */}
{i > 0 && (
<div style={{ position: 'absolute', top: -40, left: 0, right: 0, height: 40, background: 'linear-gradient(to top, rgba(0,0,0,0.30), rgba(0,0,0,0))', opacity: pushedIn < 1 ? 1 : 0 }} />
)}
</AbsoluteFill>
);
})}
</AbsoluteFill>
);
};
- 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/transition/bottom-push-stack-wipe/BottomPushStackWipe.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 |
|---|---|---|---|
| — | |||
Cùng danh mục

Chớp trắng: logo giản lược
Chữ hiệu gradient lỏng nhiều màu đứng yên chảy sáng, màn hình chớp trắng cháy sáng một nhịp, chữ hiệu phiên bản phẳng trên nền trắng mờ vào định hình — một lần chớp trắng hoàn tất bước giản lược chất liệu.

Chuyển cảnh quét hình học
Hai kiểu chuyển cảnh quét hình học — clock-wipe kim đồng hồ radar quét đổi trang và blinds-slice 12 dải dọc lật lệch nhịp thành sóng.

Chuyển cảnh giấu điểm cắt
Ba kiểu chuyển cảnh giấu điểm cắt — che khuất tiền cảnh cắt vô hình, đối đầu va chạm mở màn, và cháy sáng rò rỉ ánh sáng ấm; cắt cứng giấu trong 1-3 khung che khuất/va chạm/đỉnh sáng, khán giả không thấy kéo cắt.

Chuyển cảnh xuyên qua
Hai kiểu chuyển cảnh xuyên qua — trở về vị trí bằng phần tử chung và xuyên khoang chữ, máy quay khoan xuyên phần tử thực trong khung hình để hoàn tất đổi cảnh.