Source
92 chart lines · 2 files · 2.2 kBBenchmark harness excluded · shared/mount.ts
U.S. driving and gasoline prices55 records · CSV · 1.5 kB
@charts-poc/demo-data/drivingSelection: Complete published snapshot
- side
- string
- year
- number
- miles
- number
- gas
- number
The New York Timesobservablehq/plot@356f579b1d94 · revision 356f579b1d94 · test/data/driving.csv · Observable Plot repository MIT; upstream source credited · SHA-256 3aced2fa41f2Pinned snapshot
cases/56-connected-scatter/tanstack.ts59 lines · entry
cases/56-connected-scatter/tanstack.ts
import { arrow, d3Curve, defineChart, dot, lineY, text } from '@tanstack/charts'
import { scaleLinear } from 'd3-scale'
import { curveCatmullRom } from 'd3-shape'
import { driving } from '@charts-poc/demo-data/driving'
import { directionSegments } from './transform'
import { tanstackMount } from '../../shared/mount'
const arrows = directionSegments(driving)
const labels = driving.filter((row) => row.year % 5 === 0)
const definition = () =>
defineChart({
marks: [
lineY(driving, {
x: 'miles',
y: 'gas',
stroke: '#64748b',
strokeWidth: 2.25,
curve: d3Curve(curveCatmullRom.alpha(0.5)),
}),
dot(driving, {
x: 'miles',
y: 'gas',
fill: '#0f766e',
r: 3.25,
}),
arrow(arrows, {
x1: 'miles1',
y1: 'gas1',
x2: 'miles2',
y2: 'gas2',
stroke: '#0f766e',
strokeWidth: 1.5,
headLength: 7,
}),
text(labels, {
x: 'miles',
y: 'gas',
text: (row) => `${row.year}`,
fill: '#0f172a',
dy: -9,
}),
],
x: {
scale: scaleLinear,
grid: true,
axis: { label: 'Miles driven per person' },
},
y: {
scale: scaleLinear,
grid: true,
axis: { label: 'Cost of gasoline ($ per gallon)' },
},
})
export const mount = tanstackMount(
definition,
'Directed connected scatterplot over time',
)cases/56-connected-scatter/transform.ts33 lines · support
cases/56-connected-scatter/transform.ts
import type { DrivingRow } from '@charts-poc/demo-data/driving'
export interface DirectionSegment {
fromYear: number
toYear: number
miles1: number
gas1: number
miles2: number
gas2: number
}
export function directionSegments(
rows: readonly DrivingRow[],
): readonly DirectionSegment[] {
const targetIndexes = [14, 28, 42]
const segments: DirectionSegment[] = []
for (const targetIndex of targetIndexes) {
const source = rows[targetIndex - 1]
const target = rows[targetIndex]
if (source === undefined || target === undefined) continue
segments.push({
fromYear: source.year,
toYear: target.year,
miles1: source.miles,
gas1: source.gas,
miles2: target.miles,
gas2: target.gas,
})
}
return segments
}