Overview
@dirtytalk/spatial tracks damage as rects on top of @dirtytalk/engine, so a 2D scene graph can repaint only the regions that changed.
@dirtytalk/spatial is rect-based damage tracking for 2D scene graphs, built on @dirtytalk/engine. Nodes report what changed and where; a SceneRoot batches the reports into one frame and hands your renderer the list of rects to repaint.
Why a damage list
A dirty bit records only that something changed, so a renderer has to repaint everything. This package records a list of Damage entries instead. Each entry has a rect (the area affected) and a kind ('data', 'layout' or 'paint', which pipeline stages must run). The renderer receives the individual rects, so repaint cost scales with the damaged area rather than the scene size. See Concepts for the underlying model and Dirty channel for the engine primitive.
This package ships the Renderer2D interface, not a renderer. You supply the implementation (Canvas2D, WebGL, WebGPU, …).
Install
pnpm add @dirtytalk/spatial @dirtytalk/engine
Minimal example
import { SceneNode, SceneRoot } from '@dirtytalk/spatial';
import type { Renderer2D, Rect } from '@dirtytalk/spatial';
import { SyncScheduler } from '@dirtytalk/engine';
const renderer: Renderer2D = {
beginFrame(regions: readonly Rect[]) {
console.log('repaint', regions);
},
endFrame() {},
};
class Button extends SceneNode {
label = '';
setLabel(label: string) {
if (this.label === label) return;
this.label = label;
this.markDamaged('paint');
}
paint() {}
}
const root = new SceneRoot(renderer, {
scheduler: new SyncScheduler(),
bounds: { x: 0, y: 0, w: 800, h: 600 },
});
const button = new Button({ bounds: { x: 10, y: 10, w: 120, h: 40 } });
root.adoptChild(button); // repaint [{ x: 10, y: 10, w: 120, h: 40 }]
button.setLabel('Click me'); // repaint [{ x: 10, y: 10, w: 120, h: 40 }]
SyncScheduler flushes on every mark, which keeps the example linear. In an application, omit scheduler to use the default RAFScheduler, which coalesces all damage raised in a tick into one frame.
Pages
- Scene graph:
SceneNode,SceneRoot, damage kinds, batching, subclassing. - Rendering: the
Renderer2Dcontract, frame regions,FrameTiming, rect helpers, a Canvas2D renderer. - Pointer events: hit-testing and
PointerRouter. - API reference: every public export with signatures.
For an interactive walkthrough, see /learn/spatial/.