The page is the camera. Pan and zoom a DOM stage (any element) with one transform written through the engine's ledger, so Recall gives it back exactly. Moves ease and settle (the engine sleeps when they end); with reduced motion they jump. contain (default on) keeps the stage covering its own box, so no edge shows and the page never scrolls sideways. Coordinates: world = the stage's own untransformed CSS px (0,0 is its top-left corner); screen = the same box after the camera (what the visitor sees, in the stage's untransformed layout box).
fizlet/camera · GZIP1,385 B1.4 KB of a 1.5 KB budget
Measured on this build: minified and gzipped with everything it imports, the way npm run size checks the budget in CI.
MODULES · hosted on this site
import { camera, zoomAt, flyTo, toScreen, … } from "https://coded-dot-design.github.io/fizlet/dist/camera.js";
NPM · COMING SOON
npm install fizlet # not published yet
import { camera, zoomAt, flyTo, toScreen, … } from "fizlet/camera";
API
Every export, with its doc comment, read from the published type declarations of v0.10.0.
CameraOptions interface
export interface CameraOptions {
/** Easing rate per second (default 7; higher is snappier). A move settles in about 6 / ease s. */
ease?: number;
/** Zoom limits (default 1 and 4). */
min?: number;
max?: number;
/** Keep the stage covering its own box and clip its parent (default true). */
contain?: boolean;
/** Ease moves (default: yes, unless the visitor prefers reduced motion; then every move jumps). */
motion?: boolean;
}
camera function
export declare function camera(engine: Engine, el: HTMLElement | SVGElement, o?: CameraOptions): {
/** Show world point (x, y) at screen point (px, py) (default: the same point, a zoom about it). */
to(x: number, y: number, zoom?: number, px?: number, py?: number): void;
/** Stage size in px (untransformed), as last measured. */
readonly width: number;
readonly height: number;
/** Drag by a screen delta (px): follows at once, no easing. */
pan(dx: number, dy: number): void;
/** Back to the page as it is (zoom 1, no offset), eased. */
home(): void;
/** Screen (stage box px) to world, into `out` (no allocation). */
toWorld<T extends {
[i: number]: number;
}>(x: number, y: number, out: T): T;
readonly zoom: number;
/** Still easing toward the target. */
readonly moving: boolean;
read(): void;
step(e: Engine, dt: number): void;
render(): void;
};
Camera type
export type Camera = ReturnType<typeof camera>;
zoomAt function
Zoom about world point (x, y): it stays where it is on screen. The same as cam.to(x, y, zoom).