Aller au contenu

Beaucoup de séries ​

Trente-deux séries sur un graphique, avec un titre, des titres d'axes et une légende.

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)

Ce qu'il montre ​

  • La légende s'adapte. Sous (ou sur) le tracé, D3PLegendPanel passe ses entrées à la ligne autant qu'il faut et sa bande grandit d'autant, en prenant la place au tracé. Elle s'arrête à un tiers du graphique : au-delà, la liste défile dans sa bande. Donnez un nombre à size pour fixer la hauteur. Sur un côté du tracé, la bande a une largeur à elle (140 px par défaut), les noms longs sont coupés par une ellipse (le nom entier est le titre de l'entrée) et la liste défile.
  • Les bandes gardent leur ordre quel que soit le nombre d'entrées : le titre du graphique le plus à l'extérieur, puis la légende, puis le titre de l'axe x.
  • L'infobulle passe en colonnes, une douzaine de lignes chacune, pour que sa boîte ne dépasse pas la hauteur du graphique. Le contenu par défaut de d3pDomTooltip, D3PVTooltip et D3PRTooltip le fait ; avec votre propre balisage, les données de l'infobulle (series) sont à vous de disposer.
  • Chaque série a son point là où est le pointeur, et les entrées de la légende montrent ou cachent leur ligne.