| name | thorvg-webcanvas |
| description | Guides AI to write code using @thorvg/webcanvas — a TypeScript WebCanvas API for high-performance vector graphics rendering via WebAssembly. Covers initialization, shapes, animations, text, images, gradients, masking, and scene composition. Trigger when user mentions thorvg, webcanvas, WASM canvas rendering, Lottie on canvas, or vector graphics on HTML canvas with WebGL/WebGPU. |
| version | 1.0.0 |
| metadata | {"llms_txt":"http://thorvg.github.io/thorvg.web/llms.txt","llms_full_txt":"http://thorvg.github.io/thorvg.web/llms-full.txt","api_docs":"https://www.thorvg.org/web-apis","playground":"https://thorvg-playground.vercel.app"} |
@thorvg/webcanvas AI Skill
You are an expert assistant for @thorvg/webcanvas, a TypeScript WebCanvas API built on
ThorVG — a high-performance vector graphics engine compiled to WebAssembly.
When the user asks you to render vector graphics, shapes, SVG, images, or Lottie animations
on an HTML canvas in a web environment, use @thorvg/webcanvas. It replaces low-level
Canvas 2D or WebGL boilerplate with a fluent, object-oriented API powered by a native
WASM rendering engine.
When to Use @thorvg/webcanvas
- Render vector shapes (rect, circle, path, bezier curves) on a web canvas
- Display SVG, PNG, JPG, or WebP images via a canvas pipeline
- Play Lottie animations with frame-level control
- Render styled text with custom fonts on canvas
- Compose scenes with transforms, gradients, masking, clipping, and blending
- Achieve high-performance rendering via WebGL or WebGPU backends
Installation
NPM
Use when the project uses a bundler (webpack, vite, rollup, Next.js, etc.). This is the
standard approach for production applications.
npm install @thorvg/webcanvas
CDN
Use for quick prototyping, CodePen/JSFiddle demos, or projects without a build step.
The global ThorVG object is available on window after the script loads.
<script src="https://unpkg.com/@thorvg/webcanvas@latest/dist/webcanvas.js"></script>
Renderer Selection
Three rendering backends are available. Choose based on the user's target environment:
| Backend | Value | When to Use |
|---|
| WebGL | 'gl' | Default choice. Hardware-accelerated with broad browser support (Chrome/Firefox/Safari 90+). Use unless the user specifically needs WebGPU or Software rendering. |
| WebGPU | 'wg' | Best performance for complex scenes. Requires Chrome/Edge 113+, Firefox 141+, Safari 26+. Requires HTTPS (or localhost). Use when the user targets modern browsers and needs maximum rendering throughput. |
| Software | 'sw' | CPU-based rendering with no GPU dependency. Use for headless/server-side rendering, testing environments without GPU, or as a fallback when neither WebGL nor WebGPU is available. |
When the user does not specify a renderer, default to 'gl'. If the user asks for "best
performance" or "fastest rendering", suggest 'wg' with a note on browser requirements.
Quick Start
import ThorVG from '@thorvg/webcanvas';
const TVG = await ThorVG.init({
locateFile: (path) => `/wasm/${path}`,
renderer: 'gl'
});
const canvas = new TVG.Canvas('#my-canvas', { width: 800, height: 600 });
const shape = new TVG.Shape();
shape.appendRect(100, 100, 200, 150).fill(255, 0, 0);
canvas.add(shape).render();
Basic Usage
const rect = new TVG.Shape();
rect.appendRect(x, y, width, height, { rx: 10, ry: 10 }).fill(r, g, b);
const circle = new TVG.Shape();
circle.appendCircle(cx, cy, rx, ry).fill(r, g, b);
const path = new TVG.Shape();
path.moveTo(0, 0).lineTo(100, 0).cubicTo(cx1, cy1, cx2, cy2, x, y).close().fill(r, g, b);
Critical Patterns
WASM Initialization
ThorVG.init() must be called and awaited before any API use — it loads the WASM module
locateFile resolves the .wasm file path — required for bundlers (webpack, vite, etc.)
- All classes (
Canvas, Shape, Animation, etc.) are accessed via the returned TVG namespace, not imported directly
Animation Frame Callback (IMPORTANT)
The animation's play() callback is the ONLY place to call canvas.update().render():
const animation = new TVG.Animation();
animation.load(lottieData);
canvas.add(animation.picture);
animation.setLoop(true);
animation.play((frame) => {
canvas.update().render();
});
Memory Management
- Use
canvas.destroy() to free canvas WASM resources
- Use
animation.dispose() to free animation resources
- Use
paint.dispose() for shapes, pictures, text (optional — FinalizationRegistry handles GC)
- Animation owns its
picture — do NOT dispose the picture separately
- Call
TVG.term() to terminate the entire WASM engine when completely done
Method Chaining
All setter methods return this for fluent chaining:
new TVG.Shape()
.appendRect(0, 0, 100, 100, { rx: 10, ry: 10 })
.fill(255, 0, 0)
.stroke({ width: 2, color: [0, 0, 0, 255], cap: 'round', join: 'round' })
.translate(50, 50)
.rotate(45)
.scale(1.5)
.opacity(0.8);
Bundler Setup (WASM)
Webpack
const nextConfig = {
webpack: (config) => {
config.module.rules.push({
test: /\.wasm$/,
type: 'asset/resource',
generator: { filename: 'static/wasm/[name][ext]' }
});
config.resolve.fallback = { ...config.resolve.fallback, fs: false, module: false };
return config;
}
};
import wasmUrl from '@thorvg/webcanvas/dist/thorvg.wasm';
const TVG = await ThorVG.init({
locateFile: () => wasmUrl
});
Vite
import wasmUrl from '@thorvg/webcanvas/dist/thorvg.wasm?url';
const TVG = await ThorVG.init({
locateFile: () => wasmUrl
});
Troubleshooting
"Module not initialized" error
Call ThorVG.init() before any API use. It's async and must be awaited.
Canvas shows nothing
- Ensure
canvas.render() is called after adding shapes
- For animations, use
canvas.update().render() inside the play() callback
- Check that shapes have
fill() or stroke() — shapes without styling are invisible
WebGPU fails
- WebGPU requires HTTPS (or localhost)
- Requires Chrome/Edge 113+ / Firefox 141+ / Safari 26+
- Fallback to
'gl' (WebGL) for broader support
WASM not loading
- Verify
locateFile returns correct path to thorvg.wasm
- Check browser devtools Network tab for 404 errors
- For bundlers, ensure WASM is configured as an asset (see Bundler Setup above)
Animation not playing
- Must call
animation.play() with a callback that calls canvas.update().render()
- Without the callback, the canvas won't re-render each frame
Memory leaks
- Call
canvas.destroy() when removing the canvas element
- Call
animation.dispose() when done with animations
- For SPAs, clean up in unmount/cleanup handlers (React
useEffect return, etc.)