DOM ENGINEV0.21.3FIZLET

VIEW CANVAS V0.21.3 EXPERIMENTAL

@fzlt/core/view-canvas

One overlay canvas per root, sized for the screen's pixel density and redrawn only where something changed. The canvas covers the root's padding box (pointer-events: none, so the root keeps its input), its backing store is the CSS size × devicePixelRatio (capped by maxDpr), and drawing is in CSS px. - Dirty redraw: dirty([x, y, w, h]) grows one box (no arguments: the whole canvas); in the render phase that box, snapped out to whole device pixels, is cleared, clipped and handed to draw. Nothing dirty, nothing drawn: a still view costs no canvas work at all. - Settle: it never keeps the engine awake; dirty() wakes a settled engine for one redraw. - Layout reads only in the read phase, and only after a resize or a zoom (a ResizeObserver). - Recall: the canvas goes and the root's style comes back exactly (the engine's ledger). It has no motion of its own: reduced motion belongs to whatever moves the drawing.

@fzlt/core/view-canvas · GZIP936 B0.9 KB of a 1.2 KB budget

Measured on this build: minified and gzipped with everything it imports, the way npm run size checks the budget in CI.

STATUS · what the flags meanEXPERIMENTAL

In the package to try; no promise yet. New in E10 (diagrams); its API may still change.

SINCE
v0.21.0
SHIPPED IN
  • fizlet.com: the bricks index's brick graph
MODULES · hosted on this site
import { viewCanvas } from "https://fizlet.com/dist/view-canvas.js";
NPM · @fzlt/core
npm install @fzlt/core
import { viewCanvas } from "@fzlt/core/view-canvas";
IN SHORT
const v = viewCanvas(e, diagram, { label: "Brick graph", draw(ctx, box) { paint(ctx); } });
box.set([x - 12, y - 12, 24, 24]); // a node moved: [x, y, w, h], CSS px
v.dirty(box); // only those device pixels are cleared and redrawn; v.dirty() is all of it

API

Every export with its signature, parameters, return type, doc comment and status flag, generated at build time from the published type declarations of v0.21.3 by the TypeScript compiler. For AI agents: the whole API as plain text.

ViewCanvasOptions interface EXPERIMENTAL

Options for viewCanvas: the draw callback, the density cap and an accessible name.

export interface ViewCanvasOptions {
    /** Paint. The canvas is already cleared and clipped to `box` ([x, y, w, h], CSS px): draw the
     *  scene (anything outside the box is clipped away, so drawing it all is fine). */
    draw(ctx: CanvasRenderingContext2D, box: Float64Array): void;
    /** The most pixel density drawn (default 2: sharp on a phone, a quarter of the pixels at 4×). */
    maxDpr?: number;
    /** An accessible name: the canvas becomes role="img" (default: aria-hidden, decoration). */
    label?: string;
}

viewCanvas function EXPERIMENTAL

One overlay canvas on root, sized for the pixel density (capped by maxDpr) and redrawn only inside the dirty box: dirty([x, y, w, h]) (CSS px), or dirty() for all of it. Never keeps the engine awake; Recall removes the canvas and gives the root's style back.

viewCanvas(engine: Engine, root: HTMLElement, o: ViewCanvasOptions): ViewCanvas
engine
Engine
root
HTMLElement
Returns
ViewCanvas
Declaration
export declare function viewCanvas(engine: Engine, root: HTMLElement, o: ViewCanvasOptions): {
    canvas: HTMLCanvasElement;
    ctx: CanvasRenderingContext2D;
    /** The canvas size in CSS px, as last measured. */
    readonly width: number;
    readonly height: number;
    /** The device pixels per CSS px it draws at. */
    readonly dpr: number;
    /** Redraw box [x, y, w, h] (CSS px) on the next render; no box, the whole canvas. The box comes
     *  in an array, not as four numbers: doubles passed to a call are boxed. Wakes a settled engine. */
    dirty(b?: {
        readonly [i: number]: number;
    }): void;
    read(): void;
    render(): void;
};

ViewCanvas type EXPERIMENTAL

What viewCanvas returns: canvas, ctx, width, height, dpr and dirty(box?).

export type ViewCanvas = ReturnType<typeof viewCanvas>;