Skip to content

Scenes & transitions

View .mdllms.txt

Each scene returns a full-frame box. Children key from the scene’s own frame 0.

src/scenes/hero.ts
import { Layer, LayerAnimation } from "framefields";
import { H, PAPER, SANS, W } from "../theme.js";
export function hero() {
return Layer.box({
id: "hero",
position: "absolute", x: 0, y: 0, width: W, height: H,
background: "#000",
children: [
Layer.text("Every frame is a function of its number.", {
position: "absolute", x: 140, y: 420, width: W - 280,
fontFamily: SANS, fontSize: 120, fontWeight: 800, fill: PAPER,
}).animate(LayerAnimation.create().fadeIn(0, 18)),
],
});
}

Layer.sequence places scenes end to end, overlaps each pair by its transition, and sets every scene’s startFrame / durationFrames for you.

src/film.ts
import { Composition, Layer, Transition } from "framefields";
import { beats, FPS, H, W } from "./theme.js";
import { features, hero, outro, proof } from "./scenes/index.js";
const film = Layer.sequence(
[
{ scene: hero(), duration: beats(8) },
{ scene: features(), duration: beats(12), transition: Transition.push("left", 18) },
{ scene: proof(), duration: beats(8), transition: Transition.wipe("right", 16) },
{ scene: outro(), duration: beats(6), transition: Transition.iris(20) },
],
{ width: W, height: H },
);
const comp = new Composition({
width: W, height: H, fps: FPS,
durationMs: (film.totalFrames / FPS) * 1000, // the sequence knows its length
});
comp.add(film);

duration includes the transition. A missing transition is a cut.

Call Look Defaults
Transition.cut() hard cut —
Transition.crossfade(frames, ease) new scene fades in over the old 15, sine.inOut
Transition.fadeThrough(frames, ease) dip to background and back 20, sine.inOut
Transition.push(dir, frames, ease) new pushes old out left, 18, power3.inOut
Transition.slide(dir, frames, ease) new slides over old, which dims left, 18, power3.out
Transition.zoom(frames, ease) old grows and fades, new settles 18, power2.inOut
Transition.whip(dir, frames) fast motion-blurred push left, 10
Transition.wipe(dir, frames, ease) hard edge sweeps across (matte) left, 18, power2.inOut
Transition.iris(frames, { at, ease }) circle opens from a point (matte) 20, centre

dir is "left" | "right" | "up" | "down". at is [x, y] as fractions of the frame.

A badge, card or cursor that crosses a scene boundary with continuous position and velocity hides the cut. Put the carrier outside the sequence, on the composition, with its own keyframes spanning both scenes.