Skip to main content
Version: 0.x.x

Types Reference

These types are defined in @canvas-tile-engine/core and re-exported by the @canvas-tile-engine/react and @canvas-tile-engine/react-native bindings (which also add EngineHandle). Import them from whichever package your app already depends on — a React or React Native app does not need a direct core dependency for types.

// Vanilla / server: import from core
import type { Rect, Circle, Text, Line, PathItem, PathStyle, ImageItem, Coords } from "@canvas-tile-engine/core";

// React / React Native: import the same types (plus EngineHandle) from the binding
import type { Rect, PathItem, PathCommand, LineStyle, DrawHandle, EngineHandle } from "@canvas-tile-engine/react";

Draw Objects

Coords

type Coords = {
x: number;
y: number;
};

Rect

type Rect = {
x: number;
y: number;
size?: number;
origin?: { mode?: "cell" | "self"; x?: number; y?: number };
style?: {
fillStyle?: string;
strokeStyle?: string;
lineWidth?: number;
lineWidthPx?: number;
lineDash?: number[];
lineDashPx?: number[];
};
rotate?: number;
radius?: number | number[];
};

size, radius, style.lineWidth, and style.lineDash are world units and scale with zoom, so borders, corner rounding, and dash patterns stay proportional to the shape. style.lineWidthPx and style.lineDashPx are zoom-independent screen-pixel variants and take precedence over their world counterparts (the same pattern as Text's size/fontPx). Dash patterns follow Canvas2D setLineDash semantics; omit them for a solid border. rotate is degrees, clockwise.

Circle

type Circle = {
x: number;
y: number;
size?: number;
origin?: { mode?: "cell" | "self"; x?: number; y?: number };
style?: {
fillStyle?: string;
strokeStyle?: string;
lineWidth?: number;
lineWidthPx?: number;
lineDash?: number[];
lineDashPx?: number[];
};
};

The style fields follow the same unit convention as Rect.

Text

type Text = {
x: number;
y: number;
text: string;
size?: number;
style?: {
fillStyle?: string;
fontFamily?: string;
textAlign?: "center" | "end" | "left" | "right" | "start";
textBaseline?: "alphabetic" | "bottom" | "hanging" | "ideographic" | "middle" | "top";
};
rotate?: number;
};

size is a world-unit text size. Renderers currently draw the actual font at size * scale * 0.3, matching the existing Canvas2D behavior.

Line And Path

type Line = {
from: Coords;
to: Coords;
style?: LineStyle; // per-item override of drawLine's call-level style
data?: TData; // app data, returned on hitTest results
};

type PathItem<TData = unknown> = {
commands?: PathCommand[]; // free-form Canvas2D-style commands (curves, arcs, holes)
points?: Coords[]; // polyline vertices in world units (one of the two required)
closed?: boolean; // join the last point back to the first (points form)
fillRule?: "nonzero" | "evenodd"; // fill rule, default "nonzero"
style?: PathStyle; // per-item fill/stroke/dash/corner styling
data?: TData; // app data, returned on hitTest results
};

type LineStyle = {
strokeStyle?: string;
lineWidth?: number; // world units, scales with zoom
lineWidthPx?: number; // screen pixels, wins over lineWidth
lineDash?: number[]; // dash pattern in world units, anchored to the world
lineDashPx?: number[]; // dash pattern in screen pixels, wins over lineDash
};

PathItem describes a free-form path (open polyline, closed outline, or filled shape); PathStyle extends the LineStyle fields with fillStyle and cornerRadius/cornerRadiusPx. drawLine takes a LineStyle as its second argument as the batch default; a Line item's own style overrides it per item, unit pair by unit pair (an item that sets either width or dash field replaces that whole pair, so a world-unit value is never shadowed by the batch's *Px value). Because item styles are registration-time, they may change lineWidth/lineWidthPx — hit testing follows the item's own width. Dash patterns follow Canvas2D setLineDash semantics (odd-length patterns repeat) and flow continuously around path corners.

ImageItem<TImage>

type SpriteRect = {
x: number;
y: number;
w: number;
h: number;
};

type ImageItem<TImage = HTMLImageElement> = {
x: number;
y: number;
size?: number;
origin?: { mode?: "cell" | "self"; x?: number; y?: number };
rotate?: number;
img: TImage;
sprite?: SpriteRect;
};

TImage depends on the renderer:

RendererImage type
Canvas2D / WebGLHTMLImageElement
Skia / React NativeSkImage
Server@napi-rs/canvas Image

sprite crops a sub-rectangle from a spritesheet image before drawing.

DrawOptions

type DrawOptions = {
id?: string;
};

Optional last parameter of every draw method. id gives the registration a stable identity: re-registering with the same id replaces the previous registration (draw callback plus hit-test entries) instead of accumulating. Ids share one namespace across draw kinds and layers; static draw methods use their cacheKey as the id instead.

StyleOf and Decoration Styles

type StyleOf<TItem, TStyle> = (item: TItem) => TStyle | undefined;

type ShapeDecorationStyle = NonNullable<DrawObject["style"]>; // Rect / Circle
type TextDecorationStyle = NonNullable<Text["style"]>;
type LineDecorationStyle = Omit<LineStyle, "lineWidth" | "lineWidthPx">;
type PathDecorationStyle = Omit<PathStyle, "lineWidth" | "lineWidthPx" | "cornerRadius" | "cornerRadiusPx">;

The dynamic draw methods additionally accept styleOf in their options (RectDrawOptions, CircleDrawOptions, TextDrawOptions, LineDrawOptions, PathDrawOptions — each extends DrawOptions). The callback runs per item on every frame at paint time; returned fields overlay the item's own style for that frame, undefined leaves it untouched. Line and path decorations exclude stroke width (and corner radius), because those feed hit-test geometry resolved at registration time.

VisibleOf and InteractiveOf

type VisibleOf<TItem> = (item: TItem) => boolean | undefined;
type InteractiveOf<TItem> = (item: TItem) => boolean | undefined;

Per-item siblings of StyleOf, accepted in the same options objects and read live the same way. visibleOf returning false skips the item for the frame — it is neither painted nor hit-testable. interactiveOf returning false keeps the item painted but transparent to hitTest/hitTestFirst/hitTestRect (the per-item counterpart of hitTest: false); queries fall through to items below. true/undefined keeps the default in both. A hidden item never hit-tests, regardless of interactiveOf. visibleOf exists on all six dynamic draw options (including ImageDrawOptions); interactiveOf on the hit-tested five (TextDrawOptions has no interactiveOf — text never enters hit testing). ImageDrawOptions carries no styleOf: images have no style, appearance changes go through item fields like opacity (read live at paint time; mutate + render()).

Sprite Helpers

type SpriteSheetOptions = {
frameWidth: number;
frameHeight: number;
columns?: number;
margin?: number;
spacing?: number;
};

type SpriteAnimation = {
frames: SpriteRect[];
fps: number;
loop?: boolean;
};

Use SpriteSheet for frame math and SpriteAnimator for imperative animation. React and React Native also provide <CanvasTileEngine.Sprite>.

Callback Types

Pointer callbacks share one shape:

type MouseEventCallback = (
coords: { raw: Coords; snapped: Coords },
mouse: { raw: Coords; snapped: Coords },
client: { raw: Coords; snapped: Coords },
) => void;

Aliases:

type onClickCallback = MouseEventCallback;
type onRightClickCallback = MouseEventCallback;
type onHoverCallback = MouseEventCallback;
type onMouseDownCallback = MouseEventCallback;
type onMouseUpCallback = MouseEventCallback;
type onMouseLeaveCallback = MouseEventCallback;
type onZoomCallback = (scale: number) => void;

coords.raw is the exact world coordinate. coords.snapped is floored to the grid cell.

onWheelCallback And WheelInfo

Fires for wheel (desktop) and pinch (touch) zoom gestures (requires eventHandlers.zoom). The first three arguments match the pointer callbacks; a fourth describes the gesture:

type onWheelCallback = (
coords: { raw: Coords; snapped: Coords },
mouse: { raw: Coords; snapped: Coords },
client: { raw: Coords; snapped: Coords },
wheel: WheelInfo,
) => void;

type WheelInfo = {
deltaY: number; // negative = zoom in; synthesized for pinch
direction: "in" | "out";
source: "wheel" | "pinch";
};

onDrawCallback

type onDrawCallback = (
ctx: unknown,
coords: Coords, // top-left world coordinate of the viewport
config: Required<CanvasTileEngineConfig>, // live scale and size
transform: DrawTransform, // { worldToScreen, screenToWorld }
) => void;

The signature mirrors addDrawFunction callbacks, so custom drawing code can move between the two hooks unchanged.

ctx is renderer-specific:

  • CanvasRenderingContext2D for RendererCanvas.
  • The WebGL renderer's 2D overlay context for RendererWebGL.
  • SkCanvas for RendererSkia.
  • SKRSContext2D for RendererServer.

Engine Handles

React packages expose safe handles from useCanvasTileEngine(). Methods no-op or return defaults before mount, and engine.isReady tells you when the core instance is attached.

Common methods:

engine.render();
engine.getCenter();
engine.getVisibleBounds();
engine.setCenter({ x: 0, y: 0 });
engine.goCenter(10, 10, 500);
engine.setScale(64);
engine.goScale(64, 500);
engine.zoomIn();
engine.zoomOut();
engine.setBounds({ minX: 0, maxX: 100, minY: 0, maxY: 100 });
engine.setEventHandlers({ drag: false, hover: true });
engine.loadImage("/sprite.png");