Français
Étape 8 : autres types de graphique
Le type de graphique, c'est le rendu. Les axes, les séries, le curseur, l'infobulle restent tels quels.
ts
import {
D3PAutoDomain, d3pAutoInteractionArea, D3PAxis, D3PAxisDomain, D3PAxisTitle, D3PChart, D3PCursorIndicator,
d3pDomTooltip, D3PLegendPanel, D3PLineRenderer, D3PPanTool, D3PResetTool, D3PSeries, D3PTitle, D3PToolbox,
D3PTooltip, D3PWheelZoomTool, getGlobalBus,
D3PAutoDomain, d3pAutoInteractionArea, D3PAxis, D3PAxisDomain, D3PAxisTitle, D3PBarRenderer, D3PChart,
D3PCursorIndicator, d3pDomTooltip, D3PLegendPanel, D3PLineRenderer, D3PPanTool, D3PResetTool, D3PSeries,
D3PTitle, D3PToolbox, D3PTooltip, D3PWheelZoomTool, getGlobalBus,
} from 'd3pict'
const bus = getGlobalBus()
const container = document.getElementById('app')! // any element with a size: the chart fills it
const temperature = new D3PSeries({ bus, name: 'temperature', data: [[0, 12], [4, 9], [8, 14], [12, 21], [16, 24], [20, 17], [24, 13]] })
const feelsLike = new D3PSeries({ bus, name: 'feels like', data: [[0, 10], [4, 6], [8, 12], [12, 22], [16, 25], [20, 15], [24, 11]] })
const humidity = new D3PSeries({ bus, name: 'humidity', data: [[0, 80], [4, 85], [8, 70], [12, 45], [16, 40], [20, 60], [24, 75]] })
const hours = new D3PAxisDomain({ bus, domain: [0, 24] })
const degrees = new D3PAxisDomain({ bus, domain: [0, 30] })
const percent = new D3PAxisDomain({ bus, domain: [0, 100] })
const auto = new D3PAutoDomain({ bus })
auto.linkSeries(temperature, [hours, degrees])
auto.linkSeries(feelsLike, [hours, degrees])
const x = new D3PAxis({ bus, name: 'hour', domain: hours, props: { tickCount: 6, tickFormat: (v) => `${Math.round(v)} h`, grid: { enabled: true } } })
const y = new D3PAxis({ bus, name: 'temperature', domain: degrees, position: 'left', props: { tickFormat: (v) => `${Math.round(v * 10) / 10} °C`, grid: { enabled: true } } })
// a second Y axis, on the right, for a quantity in other units
const yRight = new D3PAxis({ bus, name: 'humidity', domain: percent, position: 'right', props: { tickFormat: (v) => `${Math.round(v)} %` } })
// one renderer per series; its style is a prop
const line = new D3PLineRenderer({ bus, series: temperature, props: { style: { color: '#e15759', curve: 'monotone', strokeWidth: 2.5 } } })
const humidityLine = new D3PLineRenderer({ bus, series: humidity, axes: ['hour', 'humidity'], props: { style: { color: '#59a14f', curve: 'monotone' } } })
// the same series, drawn as bars; a renderer is the only thing that changes
const humidityBars = new D3PBarRenderer({ bus, series: humidity, axes: ['hour', 'humidity'], props: { style: { color: '#9ccc96', barWidth: 14 } } })
const feelsLine = new D3PLineRenderer({ bus, series: feelsLike, props: { style: { color: '#4e79a7', curve: 'monotone' } } })
// what the pointer shows: a crosshair and a tooltip
const cursor = new D3PCursorIndicator({ bus })
const tooltip = new D3PTooltip({ bus })
// tools act on the domains: drag to pan, wheel to zoom
const tools = new D3PToolbox({ bus })
tools.addTool(new D3PPanTool({ bus }))
tools.addTool(new D3PWheelZoomTool({ bus }))
tools.addTool(new D3PResetTool({ bus }))
for (const name of ['pan', 'wheel-zoom', 'reset']) tools.setToolActive(name)
// titles and a legend take their room from the plot
const title = new D3PTitle({ bus, props: { text: 'Temperature', subtitle: 'on 12 June' } })
const xTitle = new D3PAxisTitle({ bus, axis: x, props: { text: 'hour of the day' } })
const yTitle = new D3PAxisTitle({ bus, axis: y, props: { text: 'temperature' } })
const yRightTitle = new D3PAxisTitle({ bus, axis: yRight, props: { text: 'humidity' } })
const legendPanel = new D3PLegendPanel({ bus, placement: 'bottom' })
const objects = [x, y, yRight, line, feelsLine, humidityLine, cursor, tooltip, tools, title, xTitle, yTitle, yRightTitle, legendPanel]
const objects = [x, y, yRight, humidityBars, line, feelsLine, cursor, tooltip, tools, title, xTitle, yTitle, yRightTitle, legendPanel]
const chart = new D3PChart({ container, bus })
const stopArea = d3pAutoInteractionArea(chart) // before the objects: the cursor, the tooltip and the tools ask for an interaction area
objects.forEach((o) => o.addToChart(chart))
const stopTooltip = d3pDomTooltip(tooltip)Ce qui a changé :
- Des barres au lieu d'une courbe. La série d'humidité est la même ;
D3PBarRendererremplaceD3PLineRenderer.barWidthest en pixels sur un axe continu, et une fraction de la bande sur un axe en bandes. - Les barres sont en premier dans la liste des objets, donc dessinées derrière les courbes : les rendus se dessinent dans l'ordre où ils sont attachés.
Pour mettre une aire sous une courbe, ajoutez un second rendu sur la même série : new D3PAreaRenderer({ bus, series, marker: false }). Son marker: false laisse le point de l'infobulle à la courbe qui la surplombe.
Les rendus
| Rendu | Dessine |
|---|---|
D3PLineRenderer, D3PAreaRenderer, D3PScatterRenderer | des courbes, des aires (jusqu'à zéro, jusqu'à une base, ou entre deux séries), des points |
D3PBarRenderer | des colonnes, des barres horizontales, des barres groupées ou empilées, des sucettes, des plages ; des barres sur axes polaires |
D3PBubbleRenderer | des points d'une taille donnée par une troisième colonne |
D3PCandlestickRenderer, D3PBoxPlotRenderer, D3PDumbbellRenderer | des séries à plusieurs valeurs par point |
D3PHeatmapRenderer | une grille colorée par une valeur (D3PColorScale, D3PColorLegend) |
D3PPieRenderer, D3PFunnelRenderer | des parts d'un tout : pas d'axes |
Certains types demandent une transformation pour préparer la série : D3PStack (aires et barres empilées, streamgraphs), D3PWaterfall, D3PHistogram. Les annotations (D3PAnnotationLine, D3PAnnotationBand, D3PAnnotationPoint, D3PAnnotationText) marquent des valeurs des axes et suivent les zooms. Elles s'arrêtent au bord du tracé : une marque dont la valeur est hors de l'axe n'est pas dessinée, ni son étiquette.
Chaque type de graphique a une page avec le graphique et le code qui le fait, et la référence des types dit comment chacun est construit.