canvas-emulator
v1.0.1
Published
A headless Canvas 2D rendering library for Node.js. Draw shapes, text, and paths using a familiar `CanvasRenderingContext2D`-style API, then export to PPM image files or raw pixel buffers — no browser required.
Downloads
205
Readme
canvas-emulator
A headless Canvas 2D rendering library for Node.js. Draw shapes, text, and paths using a familiar CanvasRenderingContext2D-style API, then export to PPM image files or raw pixel buffers — no browser required.
Installation
pnpm add canvas-emulatorQuick start
import { createCanvas, createPPM } from 'canvas-emulator';
import fs from 'fs';
const canvas = createCanvas({ width: 512, height: 512 });
const ctx = canvas.getContext2D();
// Draw a filled rectangle
ctx.fillStyle = 'blue';
ctx.fillRect(50, 50, 200, 150);
// Draw a circle
ctx.save();
ctx.beginPath();
ctx.arc(256, 256, 80, 0);
ctx.closePath();
ctx.fillStyle = '#ff6600';
ctx.fill();
ctx.restore();
// Render text
ctx.fillStyle = 'white';
ctx.fillText('Hello!', 100, 100, 48);
// Write to a PPM image file
fs.writeFileSync('output.ppm', createPPM(canvas.width, canvas.height, canvas.renderRGB()));Open PPM files with GIMP, Preview (macOS), or convert them with ImageMagick (convert output.ppm output.png).
API
Canvas
const canvas = createCanvas({ width: number, height: number });| Member | Description |
|---|---|
| canvas.width / .height | Dimensions in pixels |
| canvas.data | Raw flat RGBA array, values normalized to [0, 1] |
| canvas.at([x, y]) | Read pixel at pixel-space coordinates |
| canvas.atUV([u, v]) | Read pixel at UV coordinates ([0,1] range) |
| canvas.setAt([x, y], pixel) | Write pixel (alpha-composited) |
| canvas.each(fn) | Iterate over every pixel with (pos, uv) |
| canvas.renderRGB() | Returns [r, g, b][] — suitable for createPPM |
| canvas.renderRGBA() | Returns [r, g, b, a][] |
| canvas.getContext2D() | Returns a CanvasContext2D drawing context |
Note: All color channel values are normalized floats in
[0, 1], not[0, 255].
Context 2D
The context closely mirrors the browser CanvasRenderingContext2D:
const ctx = canvas.getContext2D();
ctx.fillStyle = 'red'; // CSS color name, #hex, or rgb()/rgba()
ctx.strokeStyle = '#00ff00';
ctx.save(); // push state
ctx.restore(); // pop state
ctx.fillRect(x, y, w, h);
ctx.strokeRect(x, y, w, h);
ctx.clearRect(x, y, w, h);
ctx.beginPath();
ctx.moveTo(x, y);
ctx.lineTo(x, y);
ctx.arc(x, y, radius, startAngle);
ctx.rect(x, y, w, h);
ctx.closePath();
ctx.fill();
ctx.stroke();
ctx.fillText(text, x, y);
ctx.fillText(text, x, y, fontSize); // fontSize in pixels (default: 48)
ctx.measureText(text); // returns { width }Supported color formats: CSS named colors (red, blue, coral, etc.), #RGB, #RRGGBB, rgb(r, g, b), rgba(r, g, b, a).
Utilities
import { createPPM, toRGB, clamp, lerp, remap, smoothstep } from 'canvas-emulator';
// PPM export
createPPM(width, height, pixels); // pixels: [r, g, b][] normalized to [0,1]
// Color parsing
toRGB('coral'); // → [1, 0.498, 0.314]
toRGB('#ff8800'); // → [1, 0.533, 0]
// Math helpers
clamp(x, min, max);
lerp(from, to, t);
remap(x, [inMin, inMax], [outMin, outMax]);
smoothstep(edge0, edge1, value);Vector math (add, sub, mul, div, scale, dot, normalize, distance, etc.) is also exported for working directly with pixel data.
Development
pnpm build # compile (outputs dist/esm and dist/cjs)
pnpm check # type-check only
pnpm test # run tests
pnpm format # format source files
npx tsx playground.ts # run the playground script