Files
hyperframes/skills/hyperframes-animation/rules/spring-pop-entrance.md
T
WaterrrForever 853256403b feat(skills): c2v mining pass — 7 new blueprints, 10 new rules, compacted recipe corpus (#2680)
* feat(skills): c2v mining pass over animation blueprints and rules

Compacts ~45 existing animation rules/blueprints into tighter recipe form
(net -3.4k lines) and adds 17 mined from the c2v corpus:

- 7 blueprints: agent-progress-theater, camera-journey, fixed-anchor-cycle,
  panel-edit-live-sync, prompt-type-submit-generate,
  transcript-scroll-artifact-reveal, zoom-out-workspace-reveal
- 10 rules: 3d-camera-flight, anchored-layout-expand, chart-scrub-readout,
  chromatic-glitch, control-target-sync, cursor-drag, gradient-text-sweep,
  multi-cursor-choreography, particle-burst, theme-crossfade-morph






Both indexes updated.

* feat(skills): sync product-launch script bank with mined blueprint roles

The role->blueprint script bank in product-launch-video/story-design.md is
kept 1:1 with blueprints-index role declarations, which the c2v mining pass
expanded. Adds the 25 missing entries (script-shape descriptor + example
lines + pattern): 13 for the 7 new blueprints, 12 for role widenings on 7
existing ones (cursor-ui-demo, dataviz-countup, titlecard-reveal, et al.),
and states the 1:1 sync contract in the bank's intro.

* docs(skills): cover constellation-hub scatter-drift variant in the script bank

Review follow-up on #2680: the SOCIAL_PROOF constellation-hub entry
patterned only the orbit shape; the c2v pass added a scatter-drift
end-card variant with the opposite geometry (no hub, no ring). Adds an
example line and extends the pattern so a scatter-drift beat's VO isn't
steered toward the orbit shape.
2026-07-21 17:28:55 +08:00

108 lines
6.4 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
---
name: spring-pop-entrance
description: The canonical entrance pop — an element (or staggered group) arrives by scaling 0 → 1 on a smooth long-tail settle (power3 default); bouncy overshoot is a rare, explicitly-playful exception. fromTo so it's correct at t=0 under seek.
metadata:
tags: spring, entrance, pop, scale, power3, settle, stagger, reveal, arrival
---
# Spring-Pop Entrance
> **Smooth beats bouncy.** This entrance defaults to a smooth long-tail settle — `power3.out` (or `expo.out` for a faster front) — that decelerates cleanly into the resting size with **no overshoot**. Bouncy `back.out` is the **#1 instant turn-off** in agent-made videos and is almost never executed well; it is a rare, explicitly-playful exception (consumer / fun brand), never the default. When unsure, settle smoothly.
THE entrance primitive: an element (or staggered group) arrives by springing from nothing — `scale: 0 → 1`, optional small `y` rise — and settles without bouncing. This is **arrival**, not reaction: distinct from [press-release-spring.md](press-release-spring.md) (a click/press → release feedback chain on an element that already rests on screen). Many blueprints used to borrow that rule to fake an entrance; reach for this instead.
## How It Works
One `fromTo` carries the whole arrival: from `{ scale: 0, opacity: 0 }` (explicit, so t=0 is correct under seek) to `{ scale: 1, opacity: 1, ease: "power3.out" }`. For a **group**, the same `fromTo` runs per element at `i * STAGGER`, capped so the group reads as one arriving beat. The `scale` grow is load-bearing; the `y` rise is garnish — drop everything else and it must still read as a clean entrance. Let the ease produce the settle: never hand-key a `scale: 1.1` mid-state (it double-bounces against the curve).
## Recipe
```html
<!-- inside a standard scene clip (hyperframes-core) -->
<div class="pop-hero" id="hero">{heroLabel}</div>
<div class="pop-grid">
<div class="pop-item">{itemA}</div>
<div class="pop-item">{itemB}</div>
<div class="pop-item">{itemC}</div>
</div>
```
```css
.pop-hero,
.pop-item {
transform-origin: 50% 50%; /* in-place pop; move to the source point for the anchored variation */
will-change: transform;
}
.pop-grid {
display: grid;
grid-template-columns: repeat(3, 1fr);
gap: GRID_GAP;
place-items: center;
}
```
```js
// Single hero pop — smooth long-tail settle, no overshoot.
tl.fromTo(
"#hero",
{ scale: 0, opacity: 0 },
{ scale: 1, opacity: 1, duration: POP_DUR, ease: "power3.out" },
ENTRY_AT,
);
// Staggered group pop — one arriving beat.
gsap.utils.toArray(".pop-item").forEach((el, i) => {
tl.fromTo(
el,
{ scale: 0, opacity: 0, y: Y_RISE },
{ scale: 1, opacity: 1, y: 0, duration: POP_DUR, ease: "power3.out" },
GROUP_ENTRY_AT + i * STAGGER,
);
});
```
## Variations
- **Calm settle** (premium / enterprise): `power3.out`, no rotation, `Y_RISE` 012px — a weighted, confident landing for a hero wordmark or product shot.
- **Firm settle** (everyday default): `power3.out` or `expo.out` for a punchier front, `Y_RISE` ~24px — cards, icons, callouts.
- **Exact-physics settle**: when the settle IS the shot, swap the ease for `springEase({ response: 0.4 })` (critically damped) from `../adapters/gsap-easing-and-stagger.md` → Spring Eases; take `duration` from the helper.
- **Origin-anchored pop**: a callout growing out of a specific point (marker, pointer tip) sets `transform-origin` to that point (e.g. `0% 100%`) so `scale: 0 → 1` reads as "emerging from the source", not "inflating in place".
- **Pop into a held slot**: land the pop and hold still — no idle loop baked into the entrance. If the held frame genuinely needs life, hand off to [sine-wave-loop.md](sine-wave-loop.md) for subtle jitter on a separate later tween; prefer revealing the next element on its VO cue.
- **Bouncy pop (RARE — explicitly-playful only)**: swap the ease for `back.out(OVERSHOOT)` and optionally settle a small `rotation: ROT_FROM → 0` so elements look hand-placed. Only for a deliberately playful register — never product / enterprise / serious tone:
```js
tl.fromTo(
el,
{ scale: 0, opacity: 0, rotation: ROT_FROM },
{ scale: 1, opacity: 1, rotation: 0, duration: POP_DUR, ease: `back.out(${OVERSHOOT})` },
GROUP_ENTRY_AT + i * STAGGER,
);
```
Even here keep `OVERSHOOT ≤ ~2` — past that it reads as cartoon wobble. Better still: the baked spring at `dampingFraction: 0.60.7` (same adapters doc) gives ~510% overshoot that reads physical where `back.out` reads cartoon.
## Values
| token | range | notes |
| ---------- | ----------------------------------------- | ---------------------------------------------------------------- |
| EASE | `power3.out` default; `expo.out` punchier | `back.out(OVERSHOOT)` only in the playful variant |
| POP_DUR | 0.40.7s | shorter = tight snap; hero must be visible by **t ≤ 0.5s** |
| STAGGER | 0.040.08s | `min(0.06, 0.5 / ITEM_COUNT)` — self-caps the window |
| ITEM_COUNT | 39 | >9 makes the stagger vanish — switch to a wipe/sweep reveal |
| Y_RISE | 032px | small; never large enough to read as a slide-up |
| ROT_FROM | 10°–+10° | playful variant only; alternate sign by index (`i % 2 ? 6 : -6`) |
| ENTRY_AT | 00.4s | a beat of quiet, but keep the subject landing by t ≤ 0.5s |
## Critical Constraints
- Default ease `power3.out` (no overshoot); `back.out` only in the explicitly-playful variant, and there `OVERSHOOT ≤ ~2`.
- `ITEM_COUNT × STAGGER ≤ ~0.5s` — the group must land inside one beat.
- Entrances state the collapsed from-state in `fromTo` — never rely on a CSS-hidden start (it renders visible before the tween claims it under seek).
- `transform-origin: 50% 50%` for an in-place pop; the source point only for the anchored variation.
- This is a finite arrival — idle motion on a held element is a separate, later `sine-wave-loop` tween.
## See also
`center-outward-expansion` (pop while radiating to slots) · `press-release-spring` (the click-feedback counterpart) · `sine-wave-loop` (post-arrival jitter, sparingly).