A PixiJS-style 2D rendering engine. Build a scene graph of shapes and render it through one of three backends (Canvas2D, WebGL, or WebGPU), chosen at runtime.
The engine is layered as Application (lifecycle / render loop) → Renderer (the backend) → a scene graph of Container (a group) → Graphics (a drawable). You add nodes to app.stage and the renderer draws them.
Browser only.ranuts/visual needs a real HTMLCanvasElement and a GPU/Canvas context. It cannot run in Node.
Create an application, draw a filled-and-stroked rectangle and a circle, and start the render loop.
import { Application, Graphics, RENDERER_TYPE } from 'ranuts/visual';const view = document.querySelector('canvas');// Application.create is async — the WebGPU backend initializes its device// asynchronously and must finish before the first render.const app = await Application.create({ view, prefer: RENDERER_TYPE.CANVAS, // CANVAS | WEB_GL | WEB_GPU backgroundColor: '#1e1e1e',});// A rectangle: red fill + a 4px blue stroke.const rect = new Graphics();rect.beginFill('#ff0000');rect.lineStyle(4, '#0000ff');rect.drawRect(20, 20, 160, 100);rect.endFill();// A circle.const circle = new Graphics();circle.beginFill('#00cc88', 0.8);circle.drawCircle(300, 120, 60);circle.endFill();// Add drawables to the stage — the ancestor of everything that gets rendered.app.stage.addChild(rect);app.stage.addChild(circle);// Start the requestAnimationFrame loop (or call app.render() for a single frame).app.start();
The engine entry point. It owns the canvas, the renderer, and the scene-graph root (stage).
Prefer the async factory Application.create(...) over new Application(...): the WebGPU backend initializes its device asynchronously and must finish before the first render. Canvas / WebGL resolve immediately, so the factory is safe and consistent for all backends.
A group node, the "group" concept of the scene graph. It holds children and transform state but renders nothing itself; drawables such as Graphics extend it. Add a Container to build subtrees that move/scale/rotate together.
The backend is chosen by IApplicationOptions.prefer (a RENDERER_TYPE); it defaults to Canvas when omitted.
CANVAS draws directly through the Canvas2D API (fillRect, arc, ctx.stroke(), …).
WEB_GL and WEB_GPU share one BatchRenderer pipeline: shapes are triangulated, packed into a single interleaved vertex buffer, and drawn in one call.
All three backends accept any CSS color: hex (#rgb / #rrggbb), named colors, rgb(), and hsl() all resolve consistently.
Stroke geometry differs by backend, by design. Line caps and joins are drawn by the browser's native ctx.stroke() on the Canvas backend, but by custom triangulation on the WebGL/WebGPU backends. The two are not pixel-identical.