Orbit
Reference

Runtime API

A scene is a pure function of time. Given the same time it draws the same frame, which is what makes scrubbing, previews and exports agree.

Writing a scene

A scene receives a context and draws one frame. Orbit writes scenes like this for every film. The example scenes are written exactly this way, so they are the best place to see the API in use.

import { fit, upper } from "../canvas"
import { settle } from "../ease"
import type { Scene } from "../types"

/** A headline that rises in, then holds. */
export const hello: Scene = (c) => {
  const { ctx, W, H, P, m, seg, headline } = c
  const enter = settle(seg(0, 0.2))
  const out = seg(0.93, 1)

  const size = fit(c, headline, m * 0.12, W * 0.86)
  ctx.fillStyle = P.fg
  ctx.globalAlpha = 1 - out
  ctx.fillText(upper(P, headline), W * 0.07, H / 2 + (1 - enter) * size)
}

Scene context

FieldTypeDescription
ctxCanvasRenderingContext2DThe canvas to draw into.
W, HnumberFrame size in device pixels.
tnumberNormalized time, 0 to 1, across the scene.
seg(a, b)(a, b) => numberProgress of t through [a, b], clamped to 0..1.
mnumbermin(W, H). Size everything from this so every format scales.
portbooleanTrue for tall frames such as 9:16.
PPackThe style pack: colors, typeface, weight, spacing, case, corners.
acstringResolved accent color.
F(size, weight?)(n, w?) => stringFont shorthand in the pack's typeface.
ls(px)(px) => voidSets letter-spacing.
headline, ostring, DrawOptionsCopy and options from the template.

Easing

Every film moves with the same small set of curves, so different scenes still feel like one brand.

  • settle(x): things arriving. Fast in, soft landing, no overshoot.
  • morph(x): one thing changing size or position. Even in and out.
  • clamp01(x): limits any value to 0..1.

Drawing helpers

  • fit(c, text, size, maxWidth): shrinks a font size until the text fits.
  • wrap(ctx, text, maxWidth): greedy word wrap with the current font.
  • upper(P, text): applies the pack's uppercase rule.
  • roundRect(ctx, x, y, w, h, r): rounded rectangle path; use P.sq for square packs.

Templates

A template picks a scene, a style pack and starter copy, and carries a version:

export default defineTemplate({
  slug: "release-notes",
  name: "Release notes",
  description: "Version number, then the highlights tick in.",
  category: "Changelog",
  version: "1.0.0",
  scenes: 3,
  duration: 45,
  film: { scene: "changelog", pack: "mono", headline: "v2.4 is out.", num: "v2.4" },
})

Bump the patch version for copy and timing changes, the minor version for new optional props, and the major version when existing films would render differently.