English
Many series
Thirty-two series on one chart, with a title, titles on the axes and a legend.
ts
import * as d3 from 'd3'
import {
D3PAutoDomain, d3pAutoInteractionArea, D3PAxis, D3PAxisDomain, D3PAxisTitle, D3PChart, D3PCursorIndicator,
d3pDomTooltip, D3PLegendPanel, D3PLineRenderer, D3PSeries, D3PTitle, D3PTooltip, getGlobalBus,
} from 'd3pict'
// your series data: replace these generators with your own values
import { indexed, walk } from './data'
const bus = getGlobalBus()
const container = document.getElementById('app')! // any element with a size: the chart fills it
const servers = Array.from({ length: 32 }, (_, i) => `server ${String(i + 1).padStart(2, '0')}`)
const series = servers.map((name, i) => new D3PSeries({ bus, name, data: indexed(walk(100 + i, 60, 15 + (i % 8) * 9, 10, 0, 100)) }))
const dx = new D3PAxisDomain({ bus, domain: [0, 59] })
const dy = new D3PAxisDomain({ bus, domain: [0, 100] })
const auto = new D3PAutoDomain({ bus })
for (const s of series) auto.linkSeries(s, [dx, dy])
const x = new D3PAxis({ bus, name: 'x', domain: dx, props: { displayName: 'minute' } })
const y = new D3PAxis({ bus, name: 'y', domain: dy, position: 'left', props: { displayName: 'load (%)', grid: { enabled: true } } })
// one color per series, spread over the rainbow
const lines = series.map((s, i) => new D3PLineRenderer({ bus, series: s, props: { style: { color: d3.interpolateRainbow(i / servers.length), strokeWidth: 1.5 } } }))
const title = new D3PTitle({ bus, props: { text: 'Load of 32 servers' } })
const xTitle = new D3PAxisTitle({ bus, axis: x })
const yTitle = new D3PAxisTitle({ bus, axis: y })
// the legend gets as many lines as it needs, then scrolls
const legendPanel = new D3PLegendPanel({ bus, placement: 'bottom' })
const cursor = new D3PCursorIndicator({ bus })
const tooltip = new D3PTooltip({ bus })
const objects = [x, y, ...lines, title, xTitle, yTitle, legendPanel, cursor, tooltip]
const chart = new D3PChart({ container, bus })
const stopArea = d3pAutoInteractionArea(chart) // before the objects: the cursor and the tooltip ask for an interaction area
objects.forEach((o) => o.addToChart(chart))
const stopTooltip = d3pDomTooltip(tooltip)What it shows
- The legend adapts. Under (or over) the plot,
D3PLegendPanelwraps its entries onto as many lines as they need and its strip grows by as much, taking the room from the plot. It stops at a third of the chart: beyond that the list scrolls in its strip. Give a number tosizeto fix the height. On a side of the plot the strip has a width of its own (140 px by default), long names are cut with an ellipsis (the whole name is the title of the entry), and the list scrolls. - The strips keep their order whatever the number of entries: the title of the chart outermost, then the legend, then the title of the x axis.
- The tooltip goes in columns, a dozen lines each, so its box does not grow taller than the chart. The default content of the tooltip of
d3pDomTooltip,D3PVTooltipandD3PRTooltipdoes it; with your own markup, the tooltip data (series) is yours to arrange. - Each series has its dot where the pointer is, and the legend entries show or hide their line.