# 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.

- Category: ui-entrance · Tags: shotcraft, remotion, ui-entrance
- Spec: 1920×1080 @ 30 fps · 5.7s (16:9)
- License: Apache-2.0 · Tier: free
- JSON: https://gimgs.net/motion/svg-shape-morph.json
- Kind: remotion
- Source (TSX): https://gimgs.net/motion/svg-shape-morph/template.html
- Repo: https://github.com/Vincentwei1021/video-shotcraft
- Credits: video-shotcraft (Vincent Wei) — https://github.com/Vincentwei1021/video-shotcraft
- Page: https://gimgs.net/motion/svg-shape-morph.html

## Params

_No params._

Default params (base64url for `?p=`): `e30`

## Prompt

## When to use

Expressing abstract "shape-shifting/adaptive/organic growth" concepts; an atmosphere beat before an opening logo, or a transition shape between chapters

## Intention

You can't make "shape changes" convincing with a cross-fade between two images — the viewer just sees two things overlapping. A true morph needs the viewer to believe this is **the same thing** all along, changing shape. Equal-count resampling plus per-point interpolation is the technical guarantee of that "sameness": no points are born or die, only radius changes. Morphing back closes the loop — seeing the round trip is what tells the viewer this is a reversible capability, not a one-time transformation.

## Duration & energy

- Duration: ~5.2s (156f@30fps)
- Energy: Low (a continuous flow with no peak, good as a voiceover backdrop or breathing beat)

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

## 意图
"形态会变"这件事，用两张图交叉淡入是说不清的——观众看到的是两个东西重叠。真正的
morph 要让观众相信这一直是**同一个东西**在改变形状。等点数重采样加逐点插值就是这个
"同一性"的技术保证：没有点的生成或消失，只有半径在变。变回原形是为了闭环——观众
看到往返，才知道这是可逆的能力而不是一次性的变身。

## 动效核心
- 两形状用极坐标函数定义，不是路径字符串：
  `rA(θ) = 76*(1 + 0.30*cos(3θ) + 0.05*sin(7θ+0.8))`、
  `rB(θ) = 76*(1 + 0.26*sin(5θ+1.2) + 0.06*cos(2θ))`——三瓣形与五瓣形，各带一层高频
  扰动做"有机"细节
- 重采样：两形状都在 `i/140 * 2π` 上取样存进 `radA/radB` 数组，天生等点数且一一对应
  ——这就是 morphTo 需要的点数对齐，只不过在极坐标下免费获得
- 插值只发生在半径上：`r = lerp(m, radA[i], radB[i])`，角度恒定。这保证插值中间态一定
  是一条不自交的闭合曲线，不会出现路径插值常见的打结
- 往返用两条窗口相减：`m1 = seg(t, 0.08, 0.42, E.inOutCubic)`（A→B）、
  `m2 = seg(t, 0.58, 0.92, E.inOutCubic)`（B→A），`m = m1 - m2`——0 是 A、1 是 B，
  中间 0.42→0.58 是 B 形态的静置段（约 25f）
- 呼吸与自转是叠加的第二层：`breath = 1 + 0.045*(sin(m1*π) + sin(m2*π))` 让缩放在两次
  变形的**中途**各鼓一次（形状最不稳定时鼓得最多）；`rot = sin(t*2π)*4°` 走一个整数
  周期，末帧回零
- 色相跟形态绑定：`hue = lerp(m, 185, 305)`，同时驱动描边 `hsl(hue,90%,66%)`、
  填充 `hsla(hue,80%,58%,.14)` 与 `drop-shadow` 光晕——颜色是形态的读数，不是独立装饰
- 字幕在 `m > 0.5` 时切换 `morphTo(shapeB)` / `morphTo(shapeA)`，透明度
  `0.4 + 0.6*|m-0.5|*2` 在形态最"纯"时最亮、变形中途最淡

## 参数表
| 参数 | 典型值 | 调节手感 |
|------|--------|----------|
| 采样点数 | N=140 | 140 点在 480×270 上足够平滑（`L` 直线段肉眼看不出）；<60 点能看到多边形棱角，>300 点是纯浪费 |
| 基半径 | BASE=76，中心 (240,138) | 76 相对 270 高度约占 56%——留边给光晕；调大要检查 `0.30` 的凸起是否顶出 viewBox |
| 形状 A | `1 + 0.30cos(3θ) + 0.05sin(7θ+0.8)` | 3θ 定瓣数、0.30 定凸起深度；深度 >0.5 时凹处半径趋近 0，形状会掐出尖角 |
| 形状 B | `1 + 0.26sin(5θ+1.2) + 0.06cos(2θ)` | 与 A 的瓣数不同（5 vs 3）才有变形张力；瓣数相同只会看到形状"转了转" |
| 变形窗 | 0.08→0.42 / 0.58→0.92，均 inOutCubic | 行程 0.34（≈53f）；inOut 的缓起缓收是"有机"的关键，换 linear 立刻读作机械插值 |
| 中段静置 | 0.42→0.58（≈25f） | 这是让观众认清 B 形态的时间；砍掉会读作一次来回摆动而不是 A→B→A |
| 呼吸幅度 | 0.045 × `sin(m*π)` | 4.5% 的呼吸在变形中途达峰；>10% 会读作缩放动画而不是形变 |
| 自转 | `sin(t*2π)*4°`（1 个整数周期） | 4° 是暗示级别的漂移，末帧回零可循环；>15° 会看出是整体旋转，与形变抢注意力 |
| 色相区间 | 185°→305°（青→紫） | 跨度 120° 让两个形态有明确的身份差；跨度 <40° 时颜色变化读不出，色相就白给了 |

## 已知坑
- 极坐标定义天生只能表达"从中心看每个角度一个半径"的形状——星形、花瓣、水滴都行，
  但**任何凹到自遮挡的形状（C 形、环形、有孔洞）都表达不出来**。要 morph 真实 logo
  轮廓必须换成路径重采样，这张卡的技术路线不适用
- 路径用 `L` 直线段拼接而非曲线段，靠点数密度掩盖。如果做大幅放大（>2 倍）或极粗
  描边，棱角会显形——放大场景要提高 N 或改用 `C` 段
- 每帧重建整条 `d` 字符串（140 点字符串拼接 × 2 个 path）。480×270 无压力，但如果同屏
  放多个实例或点数上到 500，要考虑缓存插值结果
- 两条形状函数写死在 setup 里，没有做成参数。要换形状是改函数体而不是传参——移植时
  建议把 `rA/rB` 提成入参，否则每个变体都要复制一份 setup
- 字幕 `morphTo(shapeB)` 是 anime.js API 的自我说明式占位文案，成片里应换成有语义的
  文字或直接去掉
- 背景写死 `#0a0b10`，整套颜色（90% 饱和描边 + 8px 光晕）依赖深底。白底上光晕失效，
  填充的 0.14 透明度也几乎不可见，浅色主题需要重配饱和度与描边宽度

## 参考实现
demos/ui-entrance/svg-shape-morph/
（SvgShapeMorph.tsx）

## Reference implementation (Remotion)

- demos/ui-entrance/svg-shape-morph/SvgShapeMorph.tsx — https://raw.githubusercontent.com/Vincentwei1021/video-shotcraft/main/demos/ui-entrance/svg-shape-morph/SvgShapeMorph.tsx

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


## Flow

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/ui-entrance/svg-shape-morph/SvgShapeMorph.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.

## Render

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.

## 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.
