Aller au contenu

Étape 3 : plusieurs séries et leur style ​

Un graphique peut porter autant de séries qu'on veut. Chacune est dessinée par un rendu, et un rendu reçoit son apparence par ses props.

ts
import {
  D3PAutoDomain, D3PAxis, D3PAxisDomain, D3PChart, D3PLineRenderer, D3PSeries, 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 hours = new D3PAxisDomain({ bus, domain: [0, 24] })
const degrees = new D3PAxisDomain({ bus, domain: [0, 30] })
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 } } })
const line = new D3PLineRenderer({ bus, series: temperature })
// 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 feelsLine = new D3PLineRenderer({ bus, series: feelsLike, props: { style: { color: '#4e79a7', curve: 'monotone' } } })

const objects = [x, y, line]
const objects = [x, y, line, feelsLine]

const chart = new D3PChart({ container, bus })
objects.forEach((o) => o.addToChart(chart))

Ce qui a changé :

  • Une deuxième série, un deuxième rendu. feelsLike est liée aux mêmes domaines, donc les deux courbes partagent les axes. Un rendu n'a pas d'autre idée des données que sa série.
  • Le style est une prop. props: { style: { color, curve, strokeWidth } }. curve relie les points : linear (défaut), monotone, step, stepBefore, stepAfter, basis, cardinal, catmullRom, natural. Sans couleur, un rendu en prend une d'après son nom.

Les props ​

Tout objet qui a des options a des props. Lisez-en une (line.props.style.color), changez une partie (line.props({ style: { color: 'tomato' } })) ou affectez un champ (line.props.style.strokeWidth = 4) : le graphique se redessine tout seul.

Ce qu'une série peut contenir ​

Une série est une liste de lignes. La première colonne est x, la deuxième la valeur principale ; elle peut avoir d'autres colonnes, nommées, que des rendus lisent (une aire de plage a un min et un max, un chandelier a un open, un high, un low et un close).

ts
// des lignes : [x, valeur]
new D3PSeries({ bus, name: 'a', data: [[0, 12], [4, 9]] })
// une plage : les colonnes sont nommées, un rendu prend celles dont il a besoin
new D3PSeries({ bus, name: 'band', columns: ['x', 'max', 'min'], data: [[0, 20, 10], [4, 18, 8]] })
// des nombres seuls : l'indice est x
new D3PSeries({ bus, name: 'b', data: [12, 9, 14] })
// des objets : dites d'où vient chaque colonne (une clé, ou une fonction de la ligne)
new D3PSeries({ bus, name: 'c', data: rows, fields: { x: 'date', y: 'close' } })
// des colonnes : un tableau par colonne
new D3PSeries({ bus, name: 'd', data: { x: [0, 4], y: [12, 9] } })

Pour changer les données d'une série, affectez-les : series.data = [...series.data, [x, valeur]]. Tout ce qui la dessine suit, avec une animation (voir l'étape 10 et l'exemple d'ajout et de retrait de données).

Une valeur manquante (NaN) laisse un trou dans la courbe quand le style a gaps: 'break' ; par défaut, la courbe passe par-dessus.