Skip to main content
Version: Next

Image Loader

Every renderer provides an image loader through engine.images. The returned image type depends on the renderer.

Rendererengine.images.load() resolves to
Canvas2D / WebGLHTMLImageElement
Server@napi-rs/canvas Image
SkiaSkImage

API

const image = await engine.images.load("/assets/tree.png", 1);

engine.images.get("/assets/tree.png");
engine.images.has("/assets/tree.png");
engine.images.clear();

const unsubscribe = engine.images.onLoad(() => {
engine.render();
});
unsubscribe();
MethodDescription
load(src, retry = 1)Loads and caches an image. Concurrent calls for the same src share one in-flight promise.
get(src)Returns a cached image without loading.
has(src)Checks whether a source is cached.
clear()Clears cached images and listeners.
onLoad(cb)Subscribes to successful image loads. Returns an unsubscribe function.

CORS and crossOrigin

In the browser, the Canvas2D and WebGL renderers request images with crossOrigin="anonymous" by default. That makes every image request a CORS request, so a host that does not send an Access-Control-Allow-Origin header fails the load outright instead of merely tainting the canvas.

If your tiles or sprites come from a plain bucket, a CDN, or a third-party tile server that does not send that header, pass crossOrigin: null to the renderer:

import { RendererCanvas } from "@canvas-tile-engine/renderer-canvas";

const engine = new CanvasTileEngine(wrapper, config, new RendererCanvas({ crossOrigin: null }));
ValueEffect
"anonymous" (default)CORS request without credentials. The host must send Access-Control-Allow-Origin.
"use-credentials"CORS request that carries cookies.
nullNo crossorigin attribute; an ordinary image request that never fails on a missing CORS header.
WebGL needs CORS-clean images

RendererWebGL uploads images to the GPU, which the browser refuses for a tainted image. With crossOrigin: null, any cross-origin image is skipped at draw time and logged to the console. Only opt out on WebGL if every image is same-origin — otherwise serve the images with an Access-Control-Allow-Origin header.

RendererCanvas never reads pixels back, so opting out is safe there. Tainting still blocks canvas.toDataURL() / getImageData() if you call them on the engine canvas yourself.

The server and Skia renderers do not use CORS and ignore this option.

Drawing Images

const tree = await engine.images.load("/assets/tree.png");

engine.drawImage({ x: 2, y: 3, size: 1.5, img: tree }, 2);
engine.render();

Batch related images in one call:

const [grass, water] = await Promise.all([
engine.images.load("/assets/grass.png"),
engine.images.load("/assets/water.png"),
]);

engine.drawImage(
[
{ x: 0, y: 0, size: 1, img: grass },
{ x: 1, y: 0, size: 1, img: water },
],
1,
);
engine.render();

Spritesheet Frames

Every ImageItem can draw a sub-rectangle of a larger sheet:

import { SpriteSheet } from "@canvas-tile-engine/core";

const img = await engine.images.load("/assets/units.png");
const sheet = new SpriteSheet({ frameWidth: 32, frameHeight: 32, columns: 8 });

engine.drawImage({ x: 4, y: 2, size: 1, img, sprite: sheet.frame(0, 0) }, 2);
engine.render();

Use Spritesheet & Animation for animated frame updates.