SVG Parser and Renderer for Canvas
canvg is a JavaScript library designed to parse SVG files and render them onto an HTML Canvas element. It handles various SVG features, animations, and interactions, making it suitable for displaying vector graphics in environments where direct SVG rendering might not be feasible or desired. The current stable version is 4.0.3, with recent releases addressing bug fixes and dependency updates. The project appears to have an active release cadence, with multiple minor and patch releases within major versions. A key differentiator is its versatility, supporting rendering in standard browser environments, Web Workers via OffscreenCanvas, and Node.js environments, requiring appropriate polyfills or peer dependencies for server-side rendering. It provides a programmatic API to load SVG content from URLs or strings and control its rendering lifecycle.
Common errors
-
TypeError: canvg__WEBPACK_IMPORTED_MODULE_0___default.a is not a constructor
cause Attempting to instantiate `Canvg` as a default import after v4.0.0's breaking change.fixChange your import statement from `import Canvg from 'canvg'` to `import { Canvg } from 'canvg'`. -
ReferenceError: DOMParser is not defined
cause Attempting to use `canvg.fromString` or related methods in Node.js without providing a DOMParser implementation.fixFor Node.js, pass a `DOMParser` instance (e.g., from `@xmldom/xmldom`) via the `presets.node` configuration: `presets.node({ DOMParser })`. -
ReferenceError: createCanvas is not defined
cause Attempting to use `presets.node().createCanvas` in Node.js without providing a `canvas` library implementation.fixFor Node.js, pass the `canvas` library (e.g., from `canvas` npm package) via `presets.node` configuration: `presets.node({ canvas })`. -
ReferenceError: fetch is not defined
cause Attempting to fetch external SVG resources (e.g., using `Canvg.from(ctx, url)`) in Node.js without a global `fetch` or custom `fetch` implementation.fixFor Node.js, provide a `fetch` polyfill (e.g., `node-fetch`) via the `presets.node` configuration: `presets.node({ fetch })`.
Warnings
- breaking Since v4.0.0, the `Canvg` class is no longer the default export. It must now be imported as a named export.
- breaking Version 4.0.0 dropped UMD bundle support and compatibility with older browsers. Node.js environments now require Node.js >=12.0.0.
- breaking TypeScript 4 is now a minimum requirement for projects using `canvg` v4.0.0 and above.
- breaking For server-side rendering (Node.js), `canvg` v2.0.0 introduced peer dependencies like `canvas`, `jsdom`, and `xmldom` (later `@xmldom/xmldom`). These must be installed separately.
- gotcha A prototype pollution vulnerability was fixed in v3.0.11 and subsequently in v4.0.3. Ensure you are on a patched version to mitigate this security risk.
- gotcha The internal dependency `xmldom` was replaced with `@xmldom/xmldom` in v4.0.2 to address maintenance issues and improve compatibility. If you were manually configuring `xmldom`, adjust to the new package.
Install
-
npm install canvg -
yarn add canvg -
pnpm add canvg
Imports
- Canvg
import Canvg from 'canvg'
import { Canvg } from 'canvg' - presets
import { node, offscreen } from 'canvg/presets'import { presets } from 'canvg' - Canvg
const Canvg = require('canvg')const { Canvg } = require('canvg')
Quickstart
import { promises as fs } from 'fs';
import { DOMParser } from '@xmldom/xmldom';
import { createCanvas } from 'canvas';
import fetch from 'node-fetch';
import { Canvg, presets } from 'canvg';
const preset = presets.node({
DOMParser,
canvas: { createCanvas },
fetch
});
(async () => {
const svgString = `
<svg width="200" height="200" xmlns="http://www.w3.org/2000/svg">
<rect x="10" y="10" width="180" height="180" fill="#ff0000" />
<circle cx="100" cy="100" r="80" fill="#0000ff" />
<text x="50" y="110" font-family="Arial" font-size="24" fill="white">Hello Canvg!</text>
</svg>
`;
const outputFilePath = process.env.OUTPUT_PATH ?? 'output.png';
const canvasInstance = preset.createCanvas(200, 200);
const ctx = canvasInstance.getContext('2d');
const v = Canvg.fromString(ctx, svgString, preset);
// Render only first frame, ignoring animations.
await v.render();
const pngBuffer = canvasInstance.toBuffer();
await fs.writeFile(outputFilePath, pngBuffer);
console.log(`SVG rendered to ${outputFilePath}`);
})().catch(console.error);