Motion · Entrada de UI
Platform hinge rise
A platform establishes first, two subjects flip up from adjacent hinges with a damped rebound, then a conclusion stand rises in.
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
Side-by-side entrance for two subjects/options/brands; buildings, equipment, or cards rising up from a base; explainer B-roll that needs to "lay out evidence, then draw a conclusion" in one fixed camera position
Intention
Let the platform establish itself as a credible "support relationship" first, then let the two subjects flip up from behind the platform, and the viewer will naturally read them as evidence in the same set; the conclusion stand rising up from below at the end isn't a third peer element, it's a synthesis of the first two. The fixed camera and clear occlusion order make this suited to explanatory B-roll, and the subjects can be swapped for product cards, people, buildings, or comparison options. The core isn't "something appears from below" — it's two adjacent hinges producing opposing directions of unfolding force.
Duration & energy
- Duration: About 3.5s (104f@30fps; holds still for 30f after the conclusion settles)
- Energy: Medium (the two subjects flipping up together mid-shot is the only major action; the ending is just a steady platform rise)
Shot recipe (original Chinese — timing, easing, parameter table, known pitfalls)
意图
先让平台成为可信的“承托关系”,再让两个主体从平台后方翻起,观众会自然把它们 理解为同组证据;最后从下方升起的结论台不是第三个平级元素,而是对前两者的归纳。 固定机位和明确的遮挡顺序让这张卡适合解释性 B-roll,也能换成产品卡、人物、建筑或 对比方案。核心不是“东西从下方出现”,而是两个相邻铰点产生方向相反的展开力。
动效核心
- f0–15:182×16 的梯形平台从中心 seed 以
scaleX 0.012→1建立,缓动
cubic-bezier(.16,1,.3,1);必须先看见承托面,主体才能随后成立
- f12–32:背景语境圆
scale .88→1、translateY 18→0、opacity 0→1,
比主体早 2f 起步、晚 2f 收尾,作为低能量背景层
- f14–30:左右主体共用
cubic-bezier(.4,0,.2,1),分别从translateY 112/90px
与 rotate -18°/+18° 回到 0;两块的 transform-origin 分别钉在相邻的右下/左下铰点
- f30–46:左块 1.5°、右块 -1.2° 的三半波阻尼回摆,振幅乘
(1-p)^2;
右块延迟 1f,避免完全镜像的机械感
- f52–74:结论台
translateY 96→0,opacity 在前 18% 行程先到 0.45 再收至 1;
f74–103 完全静止,让结论可读
参数表
| 参数 | 典型值 | 调节手感 | |------|--------|----------| | 平台建立 | f0–15,scaleX .012→1 | 少于 10f 像硬切,多于 22f 会拖慢主体登场 | | 语境圆 | f12–32,scale .88→1,rise 18px | 背景必须先于主体可辨认,但不能先完成太久 | | 双主体翻起 | f14–30;左 rise 112px/-18°,右 rise 90px/+18° | 命门:两块必须从相邻铰点反向展开;同向旋转会失去“打开舞台”的力学关系 | | 阻尼回摆 | 16f;左 1.5°,右 1.2°,右延迟 1f | 只允许一次可感回摆;振幅 >2° 会像卡片玩具 | | 结论台 | f52–74,rise 96px | 与主体落定至少隔 6f,避免证据和结论同时抢读 | | 收尾 hold | 30f | 结论文字若超过 8 个汉字,继续延长总时长,不要压缩升台动作 |
已知坑
- 主体必须被平台上缘或独立遮罩裁住底部;没有遮挡会暴露它们从画外平移而非从平台后翻起
transform-origin不能放在各自主体中心:中心旋转读作两张卡在晃,只有相邻底部铰点才读作展开- 左右块不要做成完全同尺寸、同高度、同振幅;轻微不对称是让双主体保持可辨认轮廓的关键
- 结论台是总结层,视觉对比应低于两个主体;若给它更深颜色或更大过冲,会反客为主
- demo 只含原创通用 DOM 形状和占位文字,不依赖复刻研究里的品牌、建筑或视频素材
参考实现
demos/ui-entrance/platform-hinge-rise/ (PlatformHingeRise.tsx)
Reference implementation (Remotion)
- demos/ui-entrance/platform-hinge-rise/PlatformHingeRise.tsx — https://raw.githubusercontent.com/Vincentwei1021/video-shotcraft/main/demos/ui-entrance/platform-hinge-rise/PlatformHingeRise.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.
- Baixe o JSON — contém a receita do plano (timing, easing, tabela de parâmetros, armadilhas) e o código TSX completo.
- Clone o repositório video-shotcraft; o componente importa fixtures de demos/_fixtures e helpers de assets/lib.
- 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/platform-hinge-rise.jsongit clone https://github.com/Vincentwei1021/video-shotcraft
# component: demos/ui-entrance/platform-hinge-rise/PlatformHingeRise.tsx
npx remotion render <CompositionId> out.mp4claude mcp add --transport http gimgs https://gimgs.net/mcp
# then: search_motion_templates / get_motion_template("platform-hinge-rise")Prompt
Use the video-shotcraft shot recipe "Platform hinge rise" (Remotion composition, Apache-2.0) published on gimgs.net. Recipe JSON (prompt = timing/easing/parameter table/pitfalls, files = TSX source): https://gimgs.net/motion/platform-hinge-rise.json Raw TSX: https://gimgs.net/motion/platform-hinge-rise/template.html Repository: https://github.com/Vincentwei1021/video-shotcraft (component: demos/ui-entrance/platform-hinge-rise/PlatformHingeRise.tsx; imports demos/_fixtures and assets/lib) Spec: 1920x1080, 30 fps, 3.52s 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/ui-entrance/platform-hinge-rise/PlatformHingeRise.tsx =====
// platform-hinge-rise — 平台建立后,两块主体从相邻底部铰点反向翻起,最后结论台升入。
// 从独立 motion-blocking 研究中整理为纯 DOM/SVG 的通用 Remotion demo。
import React from 'react';
import { Easing, interpolate, useCurrentFrame } from 'remotion';
import { DesignStage } from '../../_fixtures/Motion';
export const PLATFORM_HINGE_RISE_DURATION = 104;
const CLAMP = { extrapolateLeft: 'clamp', extrapolateRight: 'clamp' } as const;
const ease = (frame: number, start: number, end: number, from = 0, to = 1) =>
interpolate(frame, [start, Math.max(start + 1, end)], [from, to], {
...CLAMP,
easing: Easing.bezier(0.16, 1, 0.3, 1),
});
const hingeEase = (frame: number, start: number, end: number) =>
interpolate(frame, [start, Math.max(start + 1, end)], [0, 1], {
...CLAMP,
easing: Easing.bezier(0.4, 0, 0.2, 1),
});
const dampedWobble = (frame: number, start: number, duration: number, amplitude: number) => {
if (frame <= start || frame >= start + duration) return 0;
const p = (frame - start) / duration;
return amplitude * Math.sin(p * Math.PI * 3) * Math.pow(1 - p, 2);
};
const SubjectPanel: React.FC<{
side: 'left' | 'right';
progress: number;
wobble: number;
}> = ({ side, progress, wobble }) => {
const isLeft = side === 'left';
const x = isLeft ? 165 : 249;
const w = isLeft ? 92 : 78;
const h = isLeft ? 72 : 59;
const rise = isLeft ? 112 : 90;
const startRotation = isLeft ? -18 : 18;
return (
<div
style={{
position: 'absolute',
left: x,
top: 108,
width: w,
height: h,
clipPath: 'polygon(8% 10%,92% 0,100% 100%,0 100%)',
background: isLeft ? '#5f6064' : '#77787c',
boxShadow: '0 10px 22px rgba(0,0,0,.12)',
transformOrigin: isLeft ? '100% 100%' : '0% 100%',
transform: `translateY(${interpolate(progress, [0, 1], [rise, 0])}px) rotate(${interpolate(
progress,
[0, 1],
[startRotation, 0],
) + wobble}deg)`,
display: 'grid',
placeItems: 'center',
color: '#f7f7f5',
fontFamily: 'Arial, sans-serif',
fontSize: 10,
fontWeight: 800,
letterSpacing: 1,
}}
>
SUBJECT
</div>
);
};
export const PlatformHingeRise: React.FC = () => {
const frame = useCurrentFrame();
const platform = ease(frame, 0, 15, 0.012, 1);
const context = ease(frame, 12, 32);
const left = hingeEase(frame, 14, 30);
const right = hingeEase(frame, 14, 30);
const conclusion = ease(frame, 52, 74);
const leftWobble = dampedWobble(frame, 30, 16, 1.5);
const rightWobble = dampedWobble(frame, 31, 16, -1.2);
return (
<DesignStage bg="#f4f4f1" raster="zoom">
<div
style={{
position: 'absolute',
inset: 0,
overflow: 'hidden',
fontFamily: 'Arial, sans-serif',
}}
>
<div
style={{
position: 'absolute',
left: 190,
top: 65,
width: 100,
height: 100,
borderRadius: '50%',
background: '#d2d2cf',
opacity: context,
transform: `translateY(${interpolate(context, [0, 1], [18, 0])}px) scale(${interpolate(
context,
[0, 1],
[0.88, 1],
)})`,
display: 'grid',
placeItems: 'start center',
paddingTop: 17,
boxSizing: 'border-box',
color: '#77787a',
fontSize: 9,
fontWeight: 800,
letterSpacing: 0.8,
}}
>
CONTEXT
</div>
<div
style={{
position: 'absolute',
left: 149,
top: 174,
width: 182,
height: 16,
clipPath: 'polygon(5% 0,95% 0,100% 100%,0 100%)',
background: '#92928f',
transformOrigin: '50% 50%',
transform: `scaleX(${platform})`,
}}
/>
<div style={{ position: 'absolute', inset: 0, clipPath: 'inset(0 0 79px 0)' }}>
<SubjectPanel side="left" progress={left} wobble={leftWobble} />
<SubjectPanel side="right" progress={right} wobble={rightWobble} />
</div>
<div
style={{
position: 'absolute',
left: 108,
top: 205,
width: 264,
height: 74,
clipPath: 'polygon(18% 0,82% 0,100% 100%,0 100%)',
background: '#d9d9d6',
opacity: interpolate(conclusion, [0, 0.18, 1], [0, 0.45, 1], CLAMP),
transform: `translateY(${interpolate(conclusion, [0, 1], [96, 0])}px)`,
display: 'grid',
placeItems: 'start center',
paddingTop: 19,
boxSizing: 'border-box',
color: '#4f5053',
fontSize: 20,
fontWeight: 850,
letterSpacing: 1.8,
}}
>
OUTCOME
</div>
</div>
</DesignStage>
);
};
- 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/ui-entrance/platform-hinge-rise/PlatformHingeRise.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 |
|---|---|---|---|
| — | |||
Mais nesta categoria

Wall reveal: three moves
Three whole-wall batch entrances — bento cell-by-cell light-up, grid wave flip, and blueprint draw-on; all reveal in place with no displacement, complementing the fly-in, displacement-type deck-deal-flyin.

Value-stagger gradient bars
16 bars enter with delay as a time stagger, while height/hue/offset/blur each lay out as a value gradient from first to last; the second beat moves the stagger origin to center and re-lays the pulse peaking there.

SVG shape morph loop
A 140-point closed outline morphs smoothly into another and back; both shapes are resampled to equal point counts in polar coordinates with per-point radius interpolation and inOutCubic, plus a light scale breathing, slow rotation, and hue drifting 185°→305° mid-morph.

Skeleton reveal
Three-tier reveal from sketch to structure to content — hand-drawn doodles get swapped for skeleton bars, which resolve into real UI.