Chartist renders a scene as SVG in the page or as a string on the server. @chartist-js/terminal renders the same scene as text for terminals and as text art in HTML.
function toScene(config: ChartConfig, size: SceneSize): SceneNodeBuilds a chart's scene without rendering it: no DOM, timers or globals. Runs the phases resolve to scene with the config's plugins and listeners.
It takes the same config as chart(), and the SVG gets the same chart type class without className. Listeners of render and mount never run, responsive overrides and the renderer are ignored, and calling update(), detach() or destroy() on the handle a plugin gets throws. Turn the scene into markup with renderToString() from chartist/server, which re-exports this function.
Parameters
configChartConfigThe chart: data, axes, layers, plugins and listeners
sizeSceneSizeThe size to lay out at, in px, and how to measure text
Returns
The scene, its root the svg
Example
import { lineChartConfig, node, toScene } from 'chartist';
import { renderToString } from 'chartist/server';
const config = lineChartConfig(
{ labels: ['Mon', 'Tue', 'Wed', 'Thu', 'Fri'], series: [[12, 9, 7, 8, 5]] },
{
viewBox: { width: 600, height: 300 },
on: {
// Styles inside the SVG, for tools that read it on its own.
scene: ({ scene }) => ({
scene: scene.append(
node('style').text('.ct-line { fill: none; stroke: #d70206; }'),
true
)
})
}
}
);
const scene = toScene(config, { width: 600, height: 300 });
export const markup = renderToString(scene);const seriesColors: readonly string[]The default series colors, a to o, as hex: the colors of chartist/styles.css ($ct-series-colors in the Sass settings). Renderers without CSS use them to color series the way the styles do. The styles color the first fifteen series only.
Example
import { seriesColors } from 'chartist';
// The color of series `c`, the third.
export const third = seriesColors[2];function applyAttribute(element: Element, name: string, value: string | number): voidSets one scene attribute on an element as the DOM renderer does: names with a known prefix (ct:value) in their namespace, and style through the CSSOM, which a Content Security Policy allows. For renderers that change elements they keep.
Parameters
elementElementThe element to change
namestringThe attribute's name, as in a scene node's
attrsvaluestring | numberThe attribute's value
Example
import { applyAttribute } from 'chartist';
const point = document.querySelector('.ct-point');
if (point) {
applyAttribute(point, 'ct:value', 12);
applyAttribute(point, 'style', 'stroke-width: 12px;');
}function renderElement(current: SceneNode, document: Document, options?: RenderElementOptions): ElementCreates the element tree of a scene node as the DOM renderer does: SVG elements, HTML elements inside a foreignObject, attributes set with applyAttribute. For renderers that create elements.
Parameters
currentSceneNodeThe node to create
documentDocumentThe document to create the elements in
options?RenderElementOptions={}The namespace, and a callback for each created element
Returns
The node's element, with its children
Example
import { node, renderElement } from 'chartist';
const dot = renderElement(node('circle', { cx: 5, cy: 5, r: 4 }, 'ct-dot'), document);
document.querySelector('svg')?.append(dot);function domRenderer(): Renderer<DomRenderOutput>Creates the renderer chart() uses by default: it renders scenes as inline SVG into the container, replacing an earlier Chartist SVG there (as 1.x does) on every render, and measures text and reads styles for layout in the container, so its CSS applies. It ignores the previous render it gets from a chart's second render on; liveDomRenderer() from chartist/live keeps its SVG and changes it instead. Wrap it to change what every render puts on the page.
Example
import { chart, domRenderer, pie, type Renderer } from 'chartist';
const dom = domRenderer();
// The DOM renderer, with a name for screen readers on every render.
const renderer: Renderer = {
...dom,
render(scene, container) {
const output = dom.render(scene, container);
output.svg.setAttribute('role', 'img');
output.svg.setAttribute('aria-label', 'Monthly budget');
return output;
}
};
chart('#chart', {
data: { series: [50, 30, 20] },
coordinates: 'polar',
layers: [pie()],
renderer
});const textAscent: 0.85Where SVG text labels put a line's baseline: this share of the font size below the top of the line (a typical font's ascent). Lines are one font size apart, so a renderer finds a line's vertical center at y - (textAscent - 0.5) * fontSize from its y.
const estimateText: MeasureTextEstimates text size without a DOM: an average glyph is 0.6 em wide, and a line is 1.2 em high, at fontSize or else 12 px. toScene() measures with it unless you pass your own, which can build on it.
Example
import { estimateText, type MeasureText } from 'chartist';
// Bold labels: a tenth wider than the estimate.
export const measureText: MeasureText = (text, options) => {
const size = estimateText(text, options);
return { ...size, width: size.width * 1.1 };
};interface SceneSizeThe size toScene and renderForHydration() lay a chart out at, since there's no container to measure, and how to measure text there.
Properties
readonly widthnumberThe width to lay out at, in px. In
toScene(), the root svg gets it as itswidth, unless the config sets one.readonly heightnumberThe height to lay out at, in px. In
toScene(), the root svg gets it as itsheight, unless the config sets one.readonly measureText?MeasureTextText measurement for layout; an estimate by default.
readonly labels?LabelModeLabel mode when the config sets none.
svgby default intoScene(), since string output often goes to tools without HTML support;htmlinrenderForHydration(), aschart()draws them.
interface DomRenderOutput extends RenderOutputWhat domRenderer returns from render(): the inline SVG it added to the container.
Properties
readonly svgSVGSVGElementThe chart's
svgelement, in the container.readonly elementOf(node: SceneNode) => Element | undefinedThe rendered element of a scene node of this render.
readonly remove() => voidTakes the SVG out of the container again.
readonly patched?booleantruewhen the renderer changed its previous output in place with theupdateit got, instead of replacing it. Thenchangessays what it did.readonly changes?readonly SceneChange[]What the renderer did to each changed node, with
patched. Without them, the chart describes the render as a replacement.readonly animation?UpdateAnimationThe timing of the update animation the renderer started, if any. The
mountevent passes it on asanimation.
interface RenderElementOptionsWhat renderElement takes besides the node and the document.
Properties
readonly html?booleanCreates the elements in the XHTML namespace, as inside a
foreignObject.readonly created?(node: SceneNode, element: Element) => voidCalled for every node and the element created for it.
interface TextMetricsThe size of a measured text, as a MeasureText function returns it.
Properties
readonly widthnumberThe text's width in px.
readonly heightnumberThe text's height in px: one line.
readonly fontSize?numberThe font size in px the text was measured with, when known.
type LabelMode = 'html' | 'svg'How labels are drawn: HTML in a foreignObject (1.x) or SVG text.
interface MeasureTextOptionsWhat a MeasureText function gets with the text to measure.
Properties
readonly classes?readonly string[]Class names of the text, for renderers that apply CSS.
readonly fontSize?numberFont size in px. Without it, the browser measures with the CSS font size and the estimate uses 12, the size of 1.x
.ct-label.readonly rootClass?stringClasses of the chart's root svg, so chart-type CSS applies.
readonly container?ElementWhere to measure (the chart container), so its CSS applies.
type MeasureText = (text: string, options?: MeasureTextOptions) => TextMetricsMeasures how much space a text takes, in px, so labels can be wrapped and aligned. In the browser, Chartist measures with the page's fonts; toScene() estimates (0.6 em per character, 1.2 em per line) unless you pass your own in its size.
Example
import type { MeasureText } from 'chartist';
// Wider glyphs than the estimate, for a wide font.
export const measureText: MeasureText = (text, options = {}) => {
const fontSize = options.fontSize ?? 12;
return { width: text.length * fontSize * 0.7, height: fontSize * 1.25 };
};interface MeasureStyleOptionsWhat a MeasureStyle function gets with the property to read.
Properties
readonly classes?readonly string[]Class names of the element whose style is read.
readonly rootClass?stringClasses of the chart's root svg, so chart-type CSS applies.
readonly container?ElementWhere to measure (the chart container), so its CSS applies.
type MeasureStyle = (property: string, options?: MeasureStyleOptions) => string | undefinedReads a computed CSS property of an SVG path with the given classes, for values that the stylesheet decides and layout needs: the pie layer reads the stroke-width of a donut slice to fit the ring. Returns undefined when it can't tell. In the browser, Chartist reads it in the chart's container; toScene() has no stylesheet, so layout uses its defaults there.
Example
import { domRenderer, type Renderer } from 'chartist';
// The DOM renderer, but donuts are laid out for 30px rings, whatever
// the stylesheet says. Pass it as `renderer` to `chart()`.
export const renderer: Renderer = {
...domRenderer(),
measureStyle: property => (property === 'stroke-width' ? '30px' : undefined)
};type RenderCause = 'create' | 'hydrate' | 'update' | 'resize' | 'responsive' | 'fonts'Why a chart rendered: create for its first render, hydrate for the first render of a chart that took server markup over (see renderForHydration()), update for update() (and the presets' setOptions()), resize when its container's size changed, responsive when its matching responsive entries changed, fonts when web fonts finished loading.
interface SceneChangeWhat a render did to one node of the output: add for a node the previous scene didn't have, update for a node whose attributes, classes or text changed (with its previous node), remove for a node of the previous scene that's gone.
Properties
readonly op'remove' | 'update' | 'add'What happened to the node.
readonly nodeSceneNodeThe node: of the new scene, or of the previous one for
remove.readonly previous?SceneNodeThe node in the previous scene, for
update.
type Keyframes = readonly Readonly<Record<string, AttrValue>>[]The keyframes of a node's update animation: one set of attributes per progress point, in the order of the points.
interface UpdateAnimationThe timing of a render's update animation: its duration in ms and its easing as a CSS easing, such as ease-out.
Properties
readonly durationnumberThe duration in ms.
readonly easingstringThe CSS easing, such as
ease-outorcubic-bezier(0.3, 0, 0.2, 1).
interface RenderUpdate<TOutput extends RenderOutput = RenderOutput>What a renderer gets about the previous render, from a chart's second render on. A renderer can change its previous output in place with it, instead of replacing it; renderers keep no state themselves.
Properties
readonly previousTOutputWhat this renderer returned for the previous render.
readonly previousSceneSceneNodeThe previous render's scene.
readonly causeRenderCauseWhy the chart renders.
readonly labelsreadonly unknown[]The data's labels, for keys from labels.
readonly previousLabelsreadonly unknown[]The previous render's labels, for keys from labels in the previous scene.
readonly keyframes(previous: SceneNode, next: SceneNode, progress: readonly number[]) => Keyframes | undefinedAsks the chart's plugins, then the layer that drew the node, for the keyframes of a node's update at the given progress points (0 is the previous node, 1 the new one; points may lie beyond them when the easing overshoots). Returns nothing when none of them has any.
interface RenderOutputWhat a renderer returns from render(). The render and mount phase events pass it on as output.
Properties
readonly elementOf?(node: SceneNode) => Element | undefinedThe rendered element of a scene node, if the output is DOM.
readonly remove?() => voidRemoves the output again.
readonly patched?booleantruewhen the renderer changed its previous output in place with theupdateit got, instead of replacing it. Thenchangessays what it did.readonly changes?readonly SceneChange[]What the renderer did to each changed node, with
patched. Without them, the chart describes the render as a replacement.readonly animation?UpdateAnimationThe timing of the update animation the renderer started, if any. The
mountevent passes it on asanimation.
interface Renderer<TOutput extends RenderOutput = RenderOutput>Turns a scene into output. chart() renders inline SVG into its container with the DOM renderer, unless its config sets a renderer. To get markup instead, without a DOM, use toScene() and renderToString() from chartist/server. A renderer that wraps another one keeps its adopt only if it passes it on, as spreading the wrapped renderer does.
Properties
render(scene: SceneNode, target: Element, update?: RenderUpdate<TOutput>) => TOutputRenders a scene into the chart's container, after the
scenephase and on every update and resize. From the second render on, it gets the previous render asupdate: a renderer that changes its previous output in place returnspatched: trueand itschanges; one that ignoresupdatereplaces its output, as the DOM renderer does.readonly measureText?MeasureTextMeasures text for layout, in the container so its CSS applies; without it, Chartist estimates text sizes.
readonly measureStyle?MeasureStyleReads computed styles for layout, in the container so its CSS applies; without it, layout uses its defaults (a donut's ring is laid out for 60 px).
readonly labels?LabelModeThe default label mode of this renderer;
htmlif omitted.adopt?(container: Element, replay: (layout: { readonly width: number; readonly height: number; readonly labels: LabelMode }) => SceneNode) => TOutput & { readonly repaired: number } | undefinedTakes over markup from
renderForHydration()in the chart's container, instead of rendering: finds it and reads the layout its marker records, gets the scene for that layout fromreplay, binds the scene's nodes to the markup's elements and makes them whatrender()would draw. A chart calls it once, before its first render, unless it always draws a new svg; later renders go throughrender(), with the adopted output as the previous one. Returns nothing when there's no markup to take over or it doesn't match the scene, and the chart then renders as usual.liveDomRenderer()fromchartist/livehas it; the DOM renderer doesn't, since it replaces its svg on every render.