Native-first HTML-in-Canvas runtime for managed DOM surfaces in canvas applications.
Prism is not a canvas engine, UI kit, design tool, app framework, game engine, or charting library.
Author visual surfaces with HTML/CSS/SVG, compose them inside Canvas 2D workflows, and let Prism manage surface registration, bounds, paint lifecycle, invalidation, readiness, coordinate helpers, and cleanup.
Your app still owns the scene, drawing model, animation loop, app state, chart logic, game logic, templates, transforms, and interaction rules.
Prism owns the lifecycle for DOM-authored canvas surfaces.
npm i @synthesisengineering/prismimport { CanvasRuntime } from "@synthesisengineering/prism";
const runtime = new CanvasRuntime(canvas, { backend: "auto" });
const surface = runtime.registerSurface(element, {
bounds: { x: 0, y: 0, width: 1200, height: 630 }
});
runtime.onPaint(({ drawSurface }) => {
drawSurface(surface);
});
runtime.start();Use paintOnce() when code needs to wait for Prism to complete one runtime-owned paint pass. It works without starting the runtime loop.
await document.fonts.ready;
await runtime.paintOnce();
const blob = await new Promise<Blob | null>((resolve) => {
canvas.toBlob(resolve, "image/png");
});Export still uses normal canvas APIs after readiness. If a surface depends on images, make sure they are loaded or decoded before calling paintOnce().
Prism prefers native HTML-in-Canvas when available and falls back to a lower-fidelity compatibility backend when it is not.
if (runtime.backendKind !== "native") {
console.warn("Compatibility mode is lower fidelity.");
}The fallback backend is compatibility-only. It does not define the public API and is not equivalent to native HTML rendering.
Surface bounds and input coordinates use CSS pixels.
Direct drawing inside onPaint() uses the canvas backing-store pixel space.
Use runtime helpers when aligning manual canvas drawing with surface coordinates:
clientToCanvasPoint()cssLengthToCanvasPixels()cssPointToCanvasPixels()
runtime.onPaint(({ ctx, drawSurface }) => {
drawSurface(surface);
const size = runtime.cssLengthToCanvasPixels(24);
ctx.fillRect(0, 0, size, size);
});Register surfaces through the runtime:
const surface = runtime.registerSurface(element, {
bounds: { x: 0, y: 0, width: 320, height: 180 }
});Update surface bounds in CSS pixels:
surface.setBounds({ x: 24, y: 32, width: 360, height: 220 });When a surface leaves the runtime:
runtime.unregisterSurface(surface);
// or
surface.dispose();Destroy the runtime when finished:
runtime.destroy();Undrawn surfaces are inactive for pointer and focus handling until they are drawn again.
The supported package entry point is:
import { CanvasRuntime } from "@synthesisengineering/prism";
import type {
CanvasBackendKind,
CanvasBackendPreference,
CanvasPoint,
CanvasRuntimeOptions,
CanvasSurface,
PaintHandler,
SurfaceBoundsInput,
SurfaceOptions,
UpdateHandler
} from "@synthesisengineering/prism";CanvasRuntime is the only constructible public runtime class. CanvasSurface
is returned by registerSurface() and may be imported as a type, but
applications should not construct surfaces directly.
Everything outside the package root is internal. Runtime internals, backend classes, and raw HTML-in-Canvas platform wrappers are not public API.
new CanvasRuntime(canvas, options);Creates a Prism runtime for one canvas.
Options:
backend:"auto" | "native" | "fallback"
canvaswidthheightpixelRatiobackendKind
registerSurface(element, options)unregisterSurface(surface)onUpdate(handler)onPaint(handler)invalidate()paintOnce()start()stop()destroy()clientToCanvasPoint(x, y)cssLengthToCanvasPixels(length)cssPointToCanvasPixels(point)
elementisDisposedgetBounds()setBounds(bounds)dispose()
- Native HTML-in-Canvas is currently experimental.
- Fallback is compatibility-only and lower fidelity.
paintOnce()waits for one runtime-owned paint pass; it does not export image data itself.- Surface bounds and input coordinates are CSS pixels.
- Direct
ctxdrawing uses canvas backing-store pixels. - Undrawn surfaces are inactive for pointer and focus handling until they are drawn again.
- Native mode depends on browser support for HTML-in-Canvas.
- Fallback is not equivalent to native HTML rendering.
- Prism v1 is 2D-first.
- WebGL/WebGPU and renderer integrations are future-facing, not the current public API center.
Native HTML-in-Canvas currently requires a Chromium build with the
canvas-draw-element flag enabled. Chrome Canary is the primary target.
chrome://flags/#canvas-draw-elementpnpm install
pnpm typecheck
pnpm test
pnpm lint
pnpm buildPrism is built around the HTML-in-Canvas proposal and related standards work in the WICG. All credit for the underlying platform capability goes to the proposal authors and the WICG.
MIT © Synthesis