Skip to content

Slope ​

One line per country between two dates, on a point axis with a blank category at each end to leave room for the first and last points.

ts
import * as d3 from 'd3'
import {
  d3pAutoInteractionArea, D3PAxis, D3PAxisDomain, D3PChart, d3pDomLegend, d3pDomTooltip, D3PLegendBundle,
  D3PLineRenderer, D3PScatterRenderer, D3PSeries, D3PTooltip, getGlobalBus,
} from 'd3pict'
// your series data: replace these generators with your own values
import { walk } from './data'

const bus = getGlobalBus()

const container = document.getElementById('app')! // any element with a size: the chart fills it

const MONTHS = ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec']
const COLORS = d3.schemeTableau10
const month = (v: unknown) => MONTHS[Math.round(Number(v))] ?? ''
/** A series of numbers over 12 months, x being the month index. */
const monthly = (seed: number, base: number, spread: number) => walk(seed, 12, base, spread, 5, 100).map((v, i) => [i, v] as [number, number])

const data: [string, number, number][] = [['Norway', 62, 71], ['Spain', 48, 66], ['Brazil', 35, 33], ['India', 22, 41], ['Japan', 55, 49], ['Kenya', 18, 29]]
// blank categories at both ends leave room for the first and last points
const dx = new D3PAxisDomain({ bus, domain: ['', '2019', '2024', ' '] })
const dy = new D3PAxisDomain({ bus, domain: [0, 80] })
const x = new D3PAxis({ bus, name: 'x', domain: dx, scaleType: 'point' })
const y = new D3PAxis({ bus, name: 'y', domain: dy, position: 'left', props: { grid: { enabled: true } } })

const countries = data.map(([name, from, to]) => new D3PSeries({ bus, name, data: [['2019', from], ['2024', to]] }))
const lines = countries.map((series, i) => new D3PLineRenderer({ bus, series, props: { style: { color: COLORS[i], strokeWidth: 2.5 } } }))
const dots = countries.map((series, i) => new D3PScatterRenderer({ bus, series, name: `${series.name} points`, props: { style: { color: COLORS[i], radius: 5 } } }))

// the legend and the tooltip list the lines: one entry per country, not one per mark
const tooltip = new D3PTooltip({ bus, series: lines })
const legend = new D3PLegendBundle({ bus, series: lines })
const objects = [x, y, ...lines, ...dots, tooltip, legend]

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)
const stopLegend = d3pDomLegend(legend)

All the chart types · how each type is built