Skip to content
D
Documentation

Export diagrams

how-to
3 min readUpdated

This page covers live diagram exports in JavaScript, Angular, React and Vue, plus server-side SVG output; Qwik is outside its scope. Use it when you need a downloadable image or PDF from a live diagram, or a static SVG from a server process with no DOM. The server-side path uses the framework-independent static renderer.

For how to mount a diagram and obtain its live instance in JavaScript and the framework bindings, see Build runnable workflows; this page adds image and PDF downloads plus DOM-free SVG rendering.

Download an image from a live diagram

Mount a real diagram first, then call the instance's async export() method from a user action. PNG returns an image data URL; SVG returns its source string, which you can wrap in an SVG data URL for download. The export includes the diagram's rendered labels, edges and styling; PNG at scale: 2 requests a 2× raster.

  1. Mount a diagram with at least one node and edge, then call export() from a user action. The examples use the same three-node flow; their buttons download diagram.png or diagram.svg from the mounted canvas.
js
import { render } from '@grafloria/element';

const host = document.createElement('div');
host.style.height = '400px';
const pngButton = document.createElement('button');
pngButton.textContent = 'Download PNG';
const svgButton = document.createElement('button');
svgButton.textContent = 'Download SVG';
const status = document.createElement('span');
document.body.append(pngButton, svgButton, status, host);

const instance = render({
  nodes: [
    { id: 'ingest', label: 'Ingest', position: { x: 40, y: 80 }, size: { width: 150, height: 66 } },
    { id: 'transform', label: 'Transform', position: { x: 260, y: 80 }, size: { width: 150, height: 66 } },
    { id: 'publish', label: 'Publish', position: { x: 480, y: 80 }, size: { width: 150, height: 66 } },
  ],
  edges: [
    { id: 'e1', source: 'ingest', target: 'transform', label: 'rows' },
    { id: 'e2', source: 'transform', target: 'publish' },
  ],
}, host);

instance.renderNow();

function download(href, name) {
  const anchor = document.createElement('a');
  anchor.href = href;
  anchor.download = name;
  anchor.click();
}

async function downloadPng() {
  const image = await instance.export('png', { scale: 2 });
  download(image, 'diagram.png');
  status.textContent = 'PNG download started.';
}

async function downloadSvg() {
  const svg = await instance.export('svg');
  download(`data:image/svg+xml;charset=utf-8,${encodeURIComponent(svg)}`, 'diagram.svg');
  status.textContent = 'SVG download started.';
}

pngButton.addEventListener('click', downloadPng);
svgButton.addEventListener('click', downloadSvg);

After either button, the page reports that the PNG or SVG download started, and the browser downloads the selected file. The PNG contains a rasterized export; the SVG is vector markup you can open in a text editor or scale without rasterizing.

Open the live image-export demo or view its source.

Download a PDF

  1. Add a PDF action to the mounted diagram and call export('pdf'). The result is a PDF data URL, so the browser can download it with the same anchor pattern. This output is a vector PDF: node paths remain paths and labels remain selectable text.
js
import { render } from '@grafloria/element';

const host = document.createElement('div');
host.style.height = '400px';
const pdfButton = document.createElement('button');
pdfButton.textContent = 'Download PDF';
const status = document.createElement('span');
document.body.append(pdfButton, status, host);

const instance = render({
  nodes: [
    { id: 'requirements', label: 'Requirements', position: { x: 40, y: 80 }, size: { width: 170, height: 66 } },
    { id: 'design', label: 'Design', position: { x: 280, y: 80 }, size: { width: 170, height: 66 } },
    { id: 'ship', label: 'Ship', position: { x: 520, y: 80 }, size: { width: 170, height: 66 } },
  ],
  edges: [
    { id: 'e1', source: 'requirements', target: 'design' },
    { id: 'e2', source: 'design', target: 'ship' },
  ],
}, host);

instance.renderNow();

async function downloadPdf() {
  const href = await instance.export('pdf');
  const anchor = document.createElement('a');
  anchor.href = href;
  anchor.download = 'diagram.pdf';
  anchor.click();
  status.textContent = 'PDF download started.';
}

pdfButton.addEventListener('click', () => void downloadPdf());

The page reports that the PDF download started, and the browser downloads diagram.pdf. Select and copy a node label in a PDF reader to confirm that the text is selectable rather than part of a screenshot.

Open the live PDF-export demo or view its source.

Render an SVG on the server

  1. For a server-rendered artifact, call renderStatic with plain node and edge specs. It returns svg and the stylesheet css without mounting a canvas or needing a DOM. Inline the stylesheet into the SVG before writing the file so the artifact carries its styles.

This Node.js ESM example writes a self-contained diagram.svg; render the same specs again to produce the same SVG and CSS.

ts
import { writeFile } from 'node:fs/promises';
import { renderStatic } from '@grafloria/element';

const result = renderStatic({
  nodes: [
    { id: 'extract', label: 'Extract', position: { x: 40, y: 40 }, size: { width: 150, height: 66 } },
    { id: 'load', label: 'Load', position: { x: 260, y: 40 }, size: { width: 150, height: 66 } },
    { id: 'model', label: 'Model', position: { x: 150, y: 170 }, size: { width: 150, height: 66 } },
  ],
  edges: [
    { id: 'e1', source: 'extract', target: 'load' },
    { id: 'e2', source: 'extract', target: 'model' },
  ],
  width: 520,
  height: 300,
  standalone: true,
  instanceId: 'pipeline-diagram',
});

const artifact = result.svg.replace(
  /^(<svg[^>]*>)/,
  `$1<style>${result.css}</style>`,
);
async function writeArtifact(): Promise<void> {
  await writeFile('diagram.svg', artifact, 'utf8');
}

void writeArtifact();

The saved SVG contains the Extract, Load and Model nodes with their edges; the call returns { html, svg, css, snapshot }, and only svg plus its inlined CSS goes into this standalone file. renderStatic() supports SVG-rendered diagram content, not framework custom-node components.

Open the live server-side export demo or view its source.

Options and caveats

The instance's export() returns a Promise<string>: SVG source for svg, and a data: URL for PNG, JPEG, WebP and PDF. It waits for asynchronous custom-node painters before capturing them. Angular exposes the equivalent async path as exportDiagram(format, options) on the canvas component.

OptionTypeDefaultWhat it does
scalenumber1Sets raster image scale.
qualitynumber from 0 to 10.92Sets JPEG or WebP quality.
backgroundColorstringtransparentSets the export background color.
viewportRectanglecontent boundsSelects a world-space rectangle to export.
paddingnumber20Adds margin in world units around content bounds; ignored when viewport is explicit.
embedModelbooleannot specifiedEmbeds the source model in SVG metadata or a PNG text chunk for editable round-trips; JPEG and WebP ignore it.
onWarnings(warnings: string[]) => voidnot specifiedReceives fidelity warnings for the export.

export() needs a painted live canvas; call it in response to an action after mounting, not before the first paint. For SVG downloads, wrap the returned markup in an SVG data URL as the examples do. External images can depend on browser fetch/CORS access; check onWarnings when an asset or custom-node capture does not appear. The synchronous exportSvgString() and exportPdf() instance methods are alternatives when you need immediate results; they return result objects with warnings and do not wait for asynchronous painters or fetch external assets.

Was this page helpful?