diagramm
v0.1.1
Published
Async canvas chart library: line, area, bar, scatter and pie charts from a simple {x, y} shape
Maintainers
Readme
diagramm
Async canvas chart library. Draws line, area, bar, scatter and pie charts
from a simple {x, y} shape onto a <canvas>.
Install
npm install diagrammUsage
import { drawChart } from 'diagramm'
await drawChart('#my-canvas', {
x: [1, 2, 3, 4],
y: [10, 20, 15, 30]
})drawChart accepts a <canvas> element or a CSS selector string, and
always returns a Promise<void> (every function in this library is async,
so future versions can do real async work - loading fonts/images, rendering
in a worker - without changing the public API).
Chart types
Set type to choose the chart ('line' is the default):
await drawChart('#chart', {
type: 'bar', // 'line' | 'area' | 'bar' | 'scatter' | 'pie'
x: ['Q1', 'Q2', 'Q3', 'Q4'],
y: [40, 55, 32, 60]
})Each chart type lives in its own module under src/charts/ and is also
exported individually for direct use:
import { drawBar } from 'diagramm'Multiple series
Use series to draw multiple lines / grouped bars / multiple point sets in
one chart. Each series can have its own x, label and color:
await drawChart('#chart', {
type: 'line',
series: [
{ x: [1, 2, 3], y: [10, 20, 15], label: 'Einnahmen', color: '#3b82f6' },
{ x: [1, 2, 3], y: [5, 8, 12], label: 'Ausgaben', color: '#ef4444' }
]
})Combining chart types
Give a series its own type to override the chart-level type, so different
series render as different chart types in the same chart - e.g. bars with a
line and a scatter overlay, all on shared axes:
await drawChart('#chart', {
axisTitles: { x: 'Quartal', y: 'USD' },
series: [
{ type: 'bar', x: ['Q1', 'Q2', 'Q3', 'Q4'], y: [40, 55, 32, 60], label: 'Umsatz', color: '#bfdbfe' },
{ type: 'line', x: ['Q1', 'Q2', 'Q3', 'Q4'], y: [35, 50, 38, 58], label: 'Plan', color: '#ef4444' },
{ type: 'scatter', x: ['Q1', 'Q2', 'Q3', 'Q4'], y: [42, 53, 30, 62], label: 'Tatsächliche Punkte', color: '#1d4ed8' }
]
})Works for any mix of line, area, bar and scatter. pie can't be
combined with the others (it has no x/y axis) - mixing it in throws. If any
series is a bar, every series in that chart is positioned by category
index, same as a standalone bar chart, so lines/points line up with the
bars instead of their own numeric x values.
Pie charts
Pie charts reuse the same x/y shape: x holds the sector labels, y
holds the values.
await drawChart('#chart', {
type: 'pie',
x: ['Chrome', 'Firefox', 'Safari', 'Other'],
y: [60, 20, 15, 5],
color: ['#3b82f6', '#ef4444', '#f59e0b', '#9ca3af']
})Color
color accepts either a single string (applied to the whole series) or an
array of strings (cycled per point/sector):
{ color: '#3b82f6' } // one color for the whole line
{ color: ['#3b82f6', '#ef4444', '#10b981'] } // one color per point/sectorIf omitted, colors are assigned from a built-in default palette by series index.
Styling and axes
await drawChart('#chart', {
x: [1, 2, 3],
y: [10, 20, 15],
width: 600,
height: 400,
background: '#ffffff',
axisTitles: { x: 'Monat', y: 'USD' },
point: { radius: 3 },
line: { width: 2 }
})Zoom and pan
enableZoomPan wires mouse wheel zoom, drag-to-pan and double-click-to-reset
onto an already-drawn chart. It's opt-in - drawChart itself stays a
one-shot, listener-free render:
import { drawChart, enableZoomPan } from 'diagramm'
const config = { x: [...], y: [...] }
await drawChart('#chart', config)
const canvas = document.querySelector('#chart')
const controller = enableZoomPan(canvas, config)
// later, e.g. on unmount:
controller.destroy()
// or wire to a "reset zoom" button:
controller.resetView()Only meaningful for line, area and scatter (numeric x axis) -
bar (categorical x) and pie (no axis) ignore it. Zooming narrows the visible
x range; y auto-fits to whatever data falls inside it. You can also set the
initial window yourself via viewRange:
{ x: [...], y: [...], viewRange: { x: [10, 50] } }Config reference
interface ChartConfig {
type?: 'line' | 'area' | 'bar' | 'scatter' | 'pie' // default 'line'
x?: (number | string)[]
y?: number[]
label?: string
color?: string | string[]
series?: {
x: (number | string)[]
y: number[]
label?: string
color?: string | string[]
type?: 'line' | 'area' | 'bar' | 'scatter' | 'pie' // overrides the chart-level type for this series
}[]
width?: number // default 600
height?: number // default 400
background?: string // default '#ffffff'
axisTitles?: { x?: string; y?: string }
point?: { radius?: number } // default 3
line?: { width?: number } // default 2
viewRange?: { x?: [number, number] } // initial zoom window (line/area/scatter only)
}Provide either top-level x/y (shorthand for one series) or series
(for multiple). x values can be numbers or strings - strings are treated
as categories and spaced evenly.
Development
npm install
npm run build # bundle to dist/ (ESM + CJS + .d.ts) via tsup
npm test # vitest
npm run typecheck # tsc --noEmitOpen examples/index.html (after npm run build) in a browser to see all
chart types rendered side by side.
