Rendering
Render one fully materialized ChartProgram to Browser Canvas, a browser-safe
SVG string, a Node PNG file, or a single-page vector PDF. Choose the target
based on where the output runs and how it will be consumed.
At a glance
| Target | Environment | Shortest call | Use when |
|---|---|---|---|
| Browser Canvas | Browser | render(program, context) |
Drawing into an existing interactive page |
| SVG | Browser or Node.js 20+ | renderToSVG(program) |
Embedding or saving scalable markup |
| Node PNG | Node.js 20+ | renderToPNG(program, { output }) |
Producing a raster file at an explicit pixel density |
| Node PDF | Node.js 20+ | renderToPDF(program, { output }) |
Producing a selectable, single-page vector document |
Rendering consumes a completed program’s graphicSpec. It does not read
datasets, semantic encodings, context, or trace to infer missing output.
Complete example program
Every rendering fragment below continues from this complete program:
import { chart } from "ggaction";
const observations = [
{ displacement: 97, acceleration: 14.5, origin: "Japan" },
{ displacement: 140, acceleration: 15.5, origin: "USA" },
{ displacement: 86, acceleration: 16.4, origin: "Japan" }
];
const program = chart()
.createCanvas({
width: 640,
height: 400,
margin: { top: 30, right: 130, bottom: 60, left: 70 }
})
.createData({ values: observations })
.createScatterPlot({
x: "displacement",
y: "acceleration",
color: "origin",
shape: "origin"
});
Browser Canvas
In a browser page containing <canvas id="chart"></canvas>, render with its 2D
context:
import { render } from "ggaction";
const context = document.querySelector("#chart").getContext("2d");
render(program, context);
The optional pixelRatio increases physical output density while retaining
logical chart coordinates. For an HTML Canvas, ggaction also preserves the
logical CSS width and height while enlarging the backing store:
render(program, context, { pixelRatio: 2 });
Raster backing dimensions are the logical dimension multiplied by
pixelRatio, rounded to the nearest whole pixel with a minimum of one pixel.
This leaves fractional logical dimensions unchanged in CSS and SVG output.
Canvas and PNG preflight the complete allocation before changing the backing
store: each physical side is limited to 32767 pixels and the complete image
to 16777216 pixels.
SVG output
The browser-safe SVG entry returns a complete SVG document string without reading the DOM or filesystem. Assign it to a trusted application container or save the returned string with the file API available in your environment.
import { renderToSVG } from "ggaction/svg";
const svg = renderToSVG(program, {
title: "Quarterly revenue",
description: "Revenue by quarter",
resourceNamespace: "quarterlyRevenue"
});
The root width, height, and viewBox use the program’s logical Canvas
dimensions. Optional title and description strings become escaped
<title> and <desc> children. Repeated calls with the same program and
options return the same string. Resource IDs use a deterministic hash of
graphicSpec by default. When multiple copies of the same chart will coexist
in one HTML document, give each call a distinct resourceNamespace so their
gradient and clipping IDs cannot collide. It must start with an ASCII letter
and contain only ASCII letters, numbers, _, or -.
For example, a browser application can place the generated document in an existing output container:
document.querySelector("#svg-output").innerHTML = svg;
PNG output
The Node-only entry point writes a completed program directly to PNG.
import { renderToPNG } from "ggaction/png";
const result = await renderToPNG(program, {
output: "./output/chart.png",
pixelRatio: 2
});
Missing output directories are created. A logical 640×400 chart at ratio 2
produces a 1280×800 image. The result contains the absolute output, physical
width and height, pixelRatio, and byte count.
PDF output
The Node-only PDF entry writes one completed chart as one vector PDF page:
import { renderToPDF } from "ggaction/pdf";
const result = await renderToPDF(program, {
output: "./output/chart.pdf",
metadata: {
title: "Quarterly revenue",
author: "Example",
subject: "Revenue by quarter",
keywords: ["revenue", "quarterly"]
}
});
Missing output directories are created. The page width and height in PDF points
use the program’s logical Canvas dimensions. The native vector backend
represents page boxes as positive integers, so PDF output requires each logical
dimension to be an integer no larger than 16777216; unsupported dimensions
are rejected before replacing the output file. The frozen result contains the
absolute output, logical width and height, pages: 1, and byte count.
Metadata is optional; it accepts only non-empty title, author, and subject
strings plus an array of non-empty keywords.
Text remains selectable/searchable PDF text. Paths, strokes, fills, clipping,
opacity, dashes, and linear gradients remain vector output; the adapter does not
rasterize the chart or accept pixelRatio. Nested Canvas translations apply to
text as well as shapes, so concat children with different plot margins retain
their distinct title and axis-label origins in PDF output.
The current renderers support concrete canvas, collection, circle, rect, line,
text, and M/L/C/Z command-path graphics. Path and line strokes may use concrete
dash arrays. They validate values with the same concrete property contract used
by editGraphics.
Rect and closed-path fills may be solid strings or item-local linear-gradient
paint values. Gradient endpoints are normalized against the final fill geometry;
path stroke width does not expand that coordinate box. The renderer creates the
Canvas gradient only for the current draw call and never stores backend objects
in graphicSpec.
Canvas, PNG, and PDF share a native drawing backend. Before creating or changing
native output, they require every geometry and style number passed to that
backend—including path controls, nested translations, stroke/dash sizes, text
size/rotation, and resolved gradient endpoints—to have magnitude no greater
than 16777216 (2^24). Derived rect/circle and nested-clip extents, gradient
direction lengths, cumulative translations, and pixel-ratio-scaled values use
the same boundary. SVG remains browser-safe string serialization and preserves
the complete finite JavaScript number range.
Line curve actions resolve interpolation into those commands before rendering.
Canvas, SVG, and PDF execute L and cubic C segments but do not read curve
names or calculate control points.
Errors and limitations
Rendering never reads semanticSpec. Every drawable property must already be
concrete. Canvas/PNG pixelRatio must be positive at native precision, no
greater than 16777216, and produce physical dimensions within the raster
limits above. PDF is vector output and does not accept pixelRatio, but its
page and drawing geometry use the Canvas-backed native limits. Native numeric
range failures are rejected before Canvas mutation or PNG/PDF file replacement.
SVG uses neither native nor raster limits. PDF options and metadata use closed
key sets. SVG resourceNamespace follows the identifier form above, and SVG
text, attributes, titles, and descriptions reject characters that XML 1.0
cannot represent; emoji, joiners, variation selectors, and right-to-left text
remain unchanged.
Related
Canvas · Semantic and graphical state · Primitive extension API