Skip to main content
Version: Next

React Native

@canvas-tile-engine/react-native mirrors the React web API, but renders through @shopify/react-native-skia.

Use this package for native maps, game boards, minimaps, and touch-driven grid UIs.

Install

Expo:

npx expo install @shopify/react-native-skia
npm install @canvas-tile-engine/core @canvas-tile-engine/react-native @canvas-tile-engine/renderer-skia

Bare React Native:

npm install @canvas-tile-engine/core @canvas-tile-engine/react-native @canvas-tile-engine/renderer-skia @shopify/react-native-skia
cd ios && pod install

@shopify/react-native-skia must be installed directly in the app because it is a native module.

Basic Setup

import { CanvasTileEngine, useCanvasTileEngine } from "@canvas-tile-engine/react-native";
import { RendererSkia } from "@canvas-tile-engine/renderer-skia";

export function NativeMap() {
const engine = useCanvasTileEngine();

return (
<CanvasTileEngine
engine={engine}
renderer={new RendererSkia()}
config={{
scale: 32,
minScale: 8,
maxScale: 96,
size: { width: 0, height: 0 },
backgroundColor: "#0f172a",
eventHandlers: { drag: true, zoom: true, click: true },
}}
style={{ flex: 1 }}
onClick={(coords) => console.log("Tapped", coords.snapped)}
>
<CanvasTileEngine.GridLines cellSize={1} strokeStyle="#1e293b" layer={0} />
<CanvasTileEngine.Circle
items={{ x: 0, y: 0, size: 0.8, style: { fillStyle: "#22d3ee" } }}
layer={1}
/>
</CanvasTileEngine>
);
}

The native component measures its wrapping View with onLayout. config.size is used as an initial placeholder and is overridden by the measured layout size.

Draw Components

The same compound components are available:

ComponentDraws
CanvasTileEngine.Rect / StaticRectDynamic or cached rectangles.
CanvasTileEngine.Circle / StaticCircleDynamic or cached circles.
CanvasTileEngine.Image / StaticImageSkImage draw items and spritesheet source rectangles.
CanvasTileEngine.SpriteAnimated spritesheet frames.
CanvasTileEngine.GridLinesInfinite grid lines.
CanvasTileEngine.LineLine segments.
CanvasTileEngine.PathPolylines.
CanvasTileEngine.TextText in world space.
CanvasTileEngine.DrawFunctionCustom Skia drawing.

Keep large items arrays stable with useMemo or state. New array identities re-register draw callbacks and can rebuild spatial indexes.

Images And Sprites

engine.loadImage(uri) resolves to a Skia SkImage.

import { useEffect, useMemo, useState } from "react";
import {
CanvasTileEngine,
SpriteSheet,
type EngineHandle,
type SkImage,
} from "@canvas-tile-engine/react-native";

function UnitLayer({ engine }: { engine: EngineHandle }) {
const [img, setImg] = useState<SkImage | null>(null);
const sheet = useMemo(() => new SpriteSheet({ frameWidth: 32, frameHeight: 32, columns: 8 }), []);
const frames = useMemo(() => sheet.framesInRow(0, 0, 5), [sheet]);

useEffect(() => {
if (!engine.isReady) return;
engine.loadImage("https://example.com/unit.png").then(setImg);
}, [engine, engine.isReady]);

if (!img) return null;

return <CanvasTileEngine.Sprite items={{ x: 4, y: 2, size: 1, img }} frames={frames} fps={8} layer={2} />;
}

Custom Drawing

onDraw and <CanvasTileEngine.DrawFunction> receive a Skia SkCanvas.

import { Skia } from "@canvas-tile-engine/react-native";

<CanvasTileEngine.DrawFunction layer={5}>
{(canvas) => {
const paint = Skia.Paint();
paint.setColor(Skia.Color("#f97316"));
canvas.drawRect(Skia.XYWHRect(12, 12, 80, 24), paint);
}}
</CanvasTileEngine.DrawFunction>

Runtime Notes

  • config, center, and renderer are read when the native engine is created on first layout.
  • Use engine.setEventHandlers, engine.setBounds, engine.updateCoords, engine.goCoords, engine.setScale, zoomIn, and zoomOut for runtime changes.
  • Static helpers record and replay Skia pictures keyed by cacheKey.
  • The React Native wrapper owns layout, gesture responder handling, tap detection, and presentation.

Web vs Native

ConcernReact webReact Native
RendererRendererCanvas or RendererWebGLRendererSkia
MountWrapper <div> with a <canvas>Skia <Canvas> inside a <View>
StylingclassName / CSSPropertiesViewStyle
ImagesHTMLImageElementSkImage
Custom draw contextCanvas2D or overlay contextSkCanvas
InputDOM mouse/touch/wheelNative touch responder