https://github.com/seanghay/skia-web
WebAssembly bindings for the Skia graphics library
https://github.com/seanghay/skia-web
browser canvas node node-canvas skia
Last synced: 12 days ago
JSON representation
WebAssembly bindings for the Skia graphics library
- Host: GitHub
- URL: https://github.com/seanghay/skia-web
- Owner: seanghay
- License: apache-2.0
- Created: 2026-03-29T09:43:38.000Z (19 days ago)
- Default Branch: main
- Last Pushed: 2026-03-30T06:36:30.000Z (18 days ago)
- Last Synced: 2026-04-03T04:21:25.217Z (14 days ago)
- Topics: browser, canvas, node, node-canvas, skia
- Language: JavaScript
- Homepage: https://seanghay.github.io/skia-web
- Size: 12 MB
- Stars: 0
- Watchers: 0
- Forks: 0
- Open Issues: 0
-
Metadata Files:
- Readme: README.md
- License: LICENSE
Awesome Lists containing this project
README
# Skia for Web
WebAssembly bindings for the [Skia](https://skia.org) graphics library. Designed for image or document generation — export to PDF, SVG, and PNG with full text layout and custom font support.
[](https://github.com/seanghay/skia-web/actions/workflows/test.yml)

Generated by examples/node/index.js
- No GPU (CPU-only, keeps the binary small)
- No browser Canvas API emulation
- No system fonts — all fonts must be loaded manually
- Works in Node.js and browsers
## Install
```sh
npm install skia
```
## Usage
```js
import { create } from 'skia';
const CanvasKit = await create();
```
For browsers, import from the browser entry point:
```js
import { create } from 'skia/browser';
const CanvasKit = await create();
```
### Export to PDF, SVG, and PNG
Use `PictureRecorder` to record drawing commands once and replay them into multiple output formats.
```js
import fs from 'node:fs/promises';
import { create } from 'skia';
const CanvasKit = await create();
const fontData = await fs.readFile('MyFont.ttf');
const fontMgr = CanvasKit.FontMgr.FromData(fontData);
// Record drawing commands
const recorder = new CanvasKit.PictureRecorder();
const canvas = recorder.beginRecording(CanvasKit.LTRBRect(0, 0, 800, 800));
const builder = CanvasKit.ParagraphBuilder.Make(
new CanvasKit.ParagraphStyle({
textStyle: { color: CanvasKit.BLACK, fontSize: 24, fontFamilies: ['My Font'] },
}),
fontMgr
);
builder.addText('Hello, world!');
const paragraph = builder.build();
paragraph.layout(700);
canvas.drawParagraph(paragraph, 50, 100);
const picture = recorder.finishRecordingAsPicture();
// PDF
const doc = new CanvasKit.PDFDocument(new CanvasKit.PDFMetadata());
doc.beginPage(800, 800).drawPicture(picture);
doc.endPage();
await fs.writeFile('output.pdf', doc.close());
// SVG
const svg = new CanvasKit.SVGCanvas(800, 800, 1);
svg.getCanvas().drawPicture(picture);
await fs.writeFile('output.svg', svg.close());
// PNG
const surface = CanvasKit.MakeSurface(800, 800);
surface.getCanvas().drawPicture(picture);
await fs.writeFile('output.png', surface.makeImageSnapshot().encodeToBytes());
// Free WASM memory
paragraph.delete();
builder.delete();
fontMgr.delete();
picture.delete();
recorder.delete();
surface.delete();
```
## Memory management
All CanvasKit objects must be manually freed by calling `.delete()` when no longer needed. Failing to do so leaks WASM memory.
## License
Apache-2.0