← GPT-AI-VIDEO
DOCUMENT · 6.1 KB

vendor/OpenMontage/.agents/skills/hyperframes-animation/adapters/gsap-easing-and-stagger.md

Workspace snapshot · 09/04 14:52

Easing, Stagger, and Function-Based Values

Easing

Built-in eases: power1, power2, power3, power4, back, bounce, circ, elastic, expo, sine, none.

Each has .in, .out, .inOut variants.

EaseUse for
power1.out, power2.outStandard UI motion. Default for most entrances.
power3.out, power4.outPunchier deceleration. Title cards, hero reveals.
sine.inOutLong, slow, calm motion. Crossfades, ambient drift.
back.out(1.7)Slight overshoot. Playful entrances. The arg controls overshoot amount.
elastic.out(1, 0.3)Springy bounce. First arg = amplitude, second = period.
expo.inOutSnappy, dramatic. Quick transitions between hero scenes.
none (linear)Camera moves with timed counterpoint, mechanical motion.

Pick .out for entrances, .in for exits, .inOut for symmetric moves and continuous motion.

Easing Vocabulary (character & mood)

Easings are tone of voice: a video that only whispers is boring; one that varies between whisper, normal, and punch is engaging. Every composition should use at least 3 different easings — power2.out for everything produces flat, monotonous motion.

The full palette by character (each family has .in, .out, .inOut variants):

FamilyCharacterTypical use
power1–power4Gentle (1) to aggressive (4) acceleration curvesGeneral purpose. power2 is the workhorse, power4 for dramatic snaps
back(N)Overshoot then settle. N controls how far past the target (1=subtle, 4=wild)Logo reveals, badge pops, card entrances. back.out(2.5) for playful, back.out(1.2) for elegant
elastic(amp, freq)Spring bounce. amp=magnitude, freq=oscillation speedPanel scatter, energetic drops, fun reveals
bounceBall-drop bouncingPhysical interactions, icons landing, score counters
expoExtreme acceleration curve (much steeper than power4)Premium/luxury reveals, dramatic entrances
sineSmooth, organic, no hard edgesAmbient float, breathing, Ken Burns, anything that loops. .inOut for yoyo motion
circCircular acceleration (starts very fast, ends very gentle or vice versa)Camera moves, scene transitions, orbital motion
steps(N)Discrete N-step jumps, no interpolationTyping effects, cursor blink, counter ticks, retro/digital aesthetics

Mood mapping: Match easing character to the beat's emotional content. Smooth/organic easings (sine, power1) feel contemplative and drifting. Aggressive deceleration (power4.out, expo.out) feels snappy and confident. Spring overshoot (back.out) feels bouncy and physical. The storyboard's mood description should guide which character fits — not a formula.

Defaults

const tl = gsap.timeline({
  paused: true,
  defaults: { duration: 0.6, ease: "power2.out" },
});

Or globally:

gsap.defaults({ duration: 0.6, ease: "power2.out" });

Setting defaults at timeline scope is preferred — it documents the motion language of that composition in one place.

Stagger

gsap.fromTo(".item", { y: 24, opacity: 0 }, { y: 0, opacity: 1, duration: 0.5, stagger: 0.08 });

Object form:

gsap.fromTo(
  ".item",
  { y: 24, opacity: 0 },
  {
    y: 0,
    opacity: 1,
    stagger: {
      each: 0.08, // delay between each
      from: "center", // "start" | "end" | "center" | "edges" | "random" | index
      amount: 0.6, // total stagger time (overrides each if both set)
      grid: "auto", // for 2D stagger
      axis: "x" | "y",
    },
  },
);

Prefer stagger over N separate tweens with manual delays — it stays correct when the target count or order changes. Use fromTo() rather than from() so the start state is explicit (see gsap-timeline-and-labels.md → sub-composition entrances).

Function-Based Values

Any var can be a function (index, target, targets) => value:

gsap.to(".item", {
  x: (i, target, targets) => i * 50,
  rotation: (i) => (i % 2 === 0 ? 5 : -5),
  stagger: 0.1,
});

Use this for per-element values that depend on index, attributes, or measured size. Cheaper and more idiomatic than building tweens in a loop.

gsap.matchMedia (preview only)

matchMedia runs setup only when a media query matches and auto-reverts when it stops matching. It is useful for preview in the browser at different viewport sizes, and for prefers-reduced-motion. It is not a substitute for rendering at the composition's actual data-width/data-height — HyperFrames renders at a fixed viewport.

let mm = gsap.matchMedia();
mm.add(
  {
    isDesktop: "(min-width: 800px)",
    reduceMotion: "(prefers-reduced-motion: reduce)",
  },
  (context) => {
    const { isDesktop, reduceMotion } = context.conditions;
    gsap.to(".box", {
      rotation: isDesktop ? 360 : 180,
      duration: reduceMotion ? 0 : 2,
    });
  },
);