PixelArtCanvas
Top-level coordinator. Primary public API. Wires together viewport, canvas buffer, renderer, input, and SVG overlay. Owns the Brush, UVMap, line/fill/select tools, and the undo/redo History.
Constructor
new PixelArtCanvas(
parentHtmlElement: HTMLDivElement,
options?: PixelArtCanvasOptions
)Types
interface HistoryState {
canUndo: boolean;
canRedo: boolean;
}
interface PixelArtCanvasOptions {
/**
* Default interaction mode for the canvas.
* "paint" for drawing, "move" for panning, or "fill" for the paint-bucket
* flood-fill tool. If not specified, the default mode will be "paint".
*/
defaultMode?: Mode;
/**
* Global event target used by InputController for drag-continuation
* mouse tracking and keyboard/blur reporting.
* @default window
*/
window?: WindowLike;
texture?: {
defaultColor?: ColorInput;
size?: {
x: number;
y?: number; // falls back to x when omitted; default: { x: 64, y: 32 }
};
maxSize?: number; // default: 2048
init?: HTMLCanvasElement;
};
zoom?: {
default?: number; // fits texture to container; falls back to 4 if container has no size
sensitivity?: number; // default: 0.1
min?: number; // default: 1
max?: number; // default: 32
};
backgroundTransparency?: {
colors: { odd: string; even: string; }; // default: { odd: "#999", even: "#666" }
squareSize: number; // default: 8
};
/**
* Fill color for the canvas area outside the texture bounds (the "void"
* around the drawing surface). Defaults to the parent element''s own CSS
* `background-color` if it''s set and non-transparent, else `#424242`.
*/
backgroundColor?: ColorInput;
brush?: BrushOptions;
select?: {
/**
* Explicit color for the pixels vacated by a Delete, the source side of
* a Move, or the footprint a Rotate/Flip no longer occupies, in
* "select" mode - overrides the smart default below. When omitted, the
* vacated area is instead filled with the most common color among its
* neighbors, so it blends into the surrounding artwork, falling back to
* fully transparent when there are no in-bounds neighbors. Accepts a
* CSS color string or a colorjs.io `Color` instance.
* @default dominant neighbor color, transparent as the ultimate fallback
*/
eraseColor?: ColorInput;
};
/**
* Called after a draw stroke is committed to the master buffer.
* Use this hook to synchronize the edited texture with an external consumer.
*/
onDrawEnd?: () => void;
/**
* Called for every local mutation (stroke, resize, texture replace).
* Used by PixelSyncSession to forward mutations over the network.
*/
onBufferUpdated?: PixelBufferHookListener;
/** Local undo/redo stack. Disabled by default. */
history?: {
enabled?: boolean;
/** @default 10 */
limit?: number;
};
/** Called whenever the undo/redo stack changes (after push, undo, redo, or clear). */
onHistoryChange?: (state: HistoryState) => void;
/**
* Overrides for the copy/paste/undo/redo/delete key combos. Unspecified
* actions keep their default binding. Shift (line-tool arm/disarm) is not
* configurable. Also settable/readable at runtime via the `keybindings`
* property.
*/
keybindings?: Partial<KeybindingsMap>;
}Mode→"paint" | "move" | "fill" | "select" | "uv".ColorInput→string | Color(colorjs.io).BrushOptions→ Brush.md.PixelBufferHookListener→ buffer/PixelBuffer.md.KeybindingsMap→ input/Keybindings.md.
Properties
brush
readonly brush: BrushPrimary/secondary colors, opacity, size. See Brush.md.
viewport
readonly viewport: DefaultViewport // { readonly zoom: Zoom; readonly camera: Readonly<Vec2>; }Read-only camera/zoom state. Same Zoom instance as the zoom accessor below.
uv
readonly uv: UVMapUV regions: create/delete/move/select, visibility, typed events. See uv/UVMap.md.
Methods
mode
get mode(): Mode
set mode(mode: Mode)| Mode | Left-click | Right-click |
|---|---|---|
"paint" | Stroke with brush.primary. Hold Shift for straight-line. | Stroke with brush.secondary. |
"move" | Pan camera. | — |
"fill" | Flood-fill with brush.primary. | Same with brush.secondary. |
"select" | Drag to select/move rectangle. Ctrl+C/V copy/paste, Delete erase, R rotate 90°, H/V flip. | — |
"uv" | Click visible region to select/drag. Delete removes it. Regions created via uv.create(...). | — |
Navigation works in any mode: wheel zooms, middle-drag or Space+left-drag pans.
IMPORTANT
Leaving "paint" cancels an armed line. Leaving "select" clears the selection. Leaving "uv" cancels an in-progress drag but does not clear the UV selection.
tools
readonly tools: Toolset // { brush: BrushTool; fill: FillTool; select: SelectTool }Runtime tool state that has no constructor option. Persists across mode switches.
tools.brush—pickArmed,pick(x, y)tools.fill—global(contiguous vs. whole-canvas fill)tools.select—shape,hasSelection,rotate(),flipHorizontal(),flipVertical()
backgroundColor
get backgroundColor(): string
set backgroundColor(color: ColorInput)Canvas void color. Redraws immediately on set.
textureSize
get textureSize(): Vec2
set textureSize(size: Vec2)Resize the working buffer. Content beyond previous bounds is lost. Emits "resized".
commitPixels
commitPixels(pixels: Vec2[], slot?: BrushColorSlot): voidCommits a pre-computed pixel set as one atomic edit. No-op when pixels is empty. slot defaults to "primary".
undo / redo / canUndo / canRedo
undo(): boolean
redo(): boolean
canUndo(): boolean
canRedo(): booleanRequires history.enabled at construction — returns false otherwise. A successful call redraws, calls onDrawEnd, and fires onHistoryChange.
IMPORTANT
A remote resize, texture-replace, or snapshot load clears the local history stack.
texture
get texture(): Uint8ClampedArray
set texture(source: HTMLCanvasElement | HTMLImageElement)Get raw RGBA pixel data, or replace the texture from a canvas/image (resizes to match, emits "texture-replaced").
textureCanvas
textureCanvas(): HTMLCanvasElementThe off-screen canvas backing the buffer.
canvas
canvas(): HTMLCanvasElementThe visible on-screen canvas element. Useful for attaching extra event listeners.
camera
get camera(): Vec2Current camera offset { x, y } in viewport space.
zoom
get zoom(): ZoomZoom value object: .value, .min, .max, .sensitivity (min 0.01). Same instance as viewport.zoom.
keybindings
get keybindings(): Keybindings.bindings reads the current set; .patch(patch) merges overrides at runtime. Throws InvalidKeybindingError or KeybindingConflictError on bad input — previous bindings stay. See input/Keybindings.md.
centerTexture
centerTexture(): voidCenters the texture in the viewport.
parentHtmlElement / reparentCanvasTo
get parentHtmlElement(): HTMLDivElement
reparentCanvasTo(newParentElement: HTMLDivElement): voidRead or move the canvas + SVG overlay into a new DOM container.
onResize
onResize(): voidRe-reads parent dimensions and resizes the canvas/overlay to fill it. Call on window.resize. No-op if parent has zero size.
destroy
destroy(): voidRemoves event listeners and unmounts canvas + overlay from the DOM.
onBufferUpdated / applyRemoteCommand / loadSnapshot
get onBufferUpdated(): PixelBufferHookListener | undefined
set onBufferUpdated(fn: PixelBufferHookListener | undefined)
applyRemoteCommand(event: PixelBufferHookEvent): void
loadSnapshot(size: Vec2, pixels: Uint8ClampedArray, uvRegions?: UVRegion[]): voidNetwork sync hooks — used by PixelSyncSession. applyRemoteCommand applies a remote mutation without re-firing onBufferUpdated. loadSnapshot hydrates buffer + UV from a snapshot (never broadcast). See network/index.md.