Public
Edited
Jul 13, 2023
1 star
Insert cell
Insert cell
Insert cell
Insert cell
{
const { scaleLinear, scaleTime } = Scale;
const { Area, Line, LinePath } = Shape;
const { AxisLeft, AxisBottom } = Axis;
const { curveLinear } = Curve;
const $ = React.createElement;

const parseTime = d3.timeParse("%m/%e/%Y");
const formatTime = d3.timeFormat("%B");
const formatNumber = d3.format(".1f");
const margin = {
top: 20,
left: 40,
right: 160,
bottom: 40
};

const height = 500;
const h = height - margin.top - margin.bottom;
const w = width - margin.left - margin.right;

const TrumpPolls = polls.filter((d, i) => d.president === 'Donald Trump' && i % 2 === 0)
const TrumpTrends = trends.filter((d, i) => d.president === 'Donald Trump' && i % 7 === 0)
const x = d => parseTime(d.modeldate);
const xValues = TrumpTrends.map(d => x(d));
const approve = d => parseFloat(d.approve_estimate);
const disapprove = d => parseFloat(d.disapprove_estimate);
const xScale = scaleTime({ range: [0, w], domain: [Math.min(...xValues), Math.max(...xValues)] });
const yScale = scaleLinear({ range: [h, 0], domain: [20, 80] });

const Chart = function() {
return (
$('svg', { width, height }, [
$(Line, {
from: { x: w + margin.left, y: 10 },
to: { x: w + margin.left, y: height - margin.top },
stroke: "#5b5e5f",
strokeDasharray: "2,2",
strokeWidth: 2,
}),
$(AxisBottom, {
left: margin.left,
top: height - margin.bottom,
scale: xScale,
stroke: '#f0f0f0',
numTicks: 7,
tickStroke: '#f0f0f0',
tickFormat: value => formatTime(value).toUpperCase(),
tickLabelProps: value => {
return {
fontSize: 8,
fill: '#999',
fontFamily: 'helvetica',
textAnchor: 'middle',
}
}
}),
$(AxisLeft, {
left: margin.left,
top: margin.top,
scale: yScale,
stroke: '#f0f0f0',
tickStroke: '#f0f0f0',
tickValues: [20, 30, 40, 50, 60, 70, 80],
tickFormat: (value) => value === 80 ? `80%` : value,
tickLabelProps: (value) => {
return {
fontSize: 13,
fill: value === 50 ? '#111' : '#999',
fontFamily: 'monospace',
fontWeight: 600,
dy: '0.32em',
dx: '-.1em',
textAnchor: 'end'
}
}
}),
$(Group.Group, { left: margin.left, top: margin.top }, [
$(Area, {
data: TrumpTrends,
x: d => xScale(x(d)),
y0: d => yScale(parseFloat(d.disapprove_lo)),
y1: d => yScale(parseFloat(d.disapprove_hi)),
stroke: 'none',
fill: '#ff7400',
fillOpacity: 0.15
}),
$(Area, {
data: TrumpTrends,
x: d => xScale(x(d)),
y0: d => yScale(parseFloat(d.approve_lo)),
y1: d => yScale(parseFloat(d.approve_hi)),
stroke: 'none',
fill: '#009e29',
fillOpacity: 0.15
}),
...TrumpPolls.map((poll,i) => {
return (
$(React.Fragment, { key: `poll-${i}` }, [
$('circle', {
cx: xScale(parseTime(poll.enddate)),
cy: yScale(poll.approve),
r: 3,
fill: '#009f29',
fillOpacity: 0.1
}),
$('circle', {
cx: xScale(parseTime(poll.enddate)),
cy: yScale(poll.disapprove),
r: 3,
fill: '#ff7400',
fillOpacity: 0.1
})
])
);
}),
$(Line, {
from: { x: -8, y: yScale(50) },
to: { x: w, y: yScale(50) },
stroke: 'black'
}),
$(LinePath, {
data: TrumpTrends,
y: d => yScale(disapprove(d)),
x: d => xScale(x(d)),
strokeWidth: 3,
stroke: '#ff7400'
}),
$(LinePath, {
curve: curveLinear,
data: TrumpTrends,
y: d => yScale(approve(d)),
x: d => xScale(x(d)),
strokeWidth: 3,
stroke: '#009e29'
}),
$('text', {
fontFamily: 'helvetica',
fontSize: 32,
fontWeight: 700,
fill: '#ff7400',
dx: '.2em',
x: xScale(x(TrumpTrends[0])),
y: yScale(disapprove(TrumpTrends[0])),
}, [
$('tspan', null, formatNumber(disapprove(TrumpTrends[0]))),
$('tspan', { fontSize: 14, dy: '-.8em' }, '%'),
$('tspan', { fontSize: 14, dx: '.2em', fill: '#222', fontWeight: 400 }, 'Disapprove')
]
),
$('text', {
fontFamily: 'helvetica',
fontSize: 32,
fontWeight: 700,
fill: '#009e29',
dx: '.2em',
x: xScale(x(TrumpTrends[0])),
y: yScale(approve(TrumpTrends[0])),
}, [
$('tspan', null, formatNumber(approve(TrumpTrends[0]))),
$('tspan', { fontSize: 14, dy: '-.8em' }, '%'),
$('tspan', { fontSize: 14, dx: '.25em', fill: '#222', fontWeight: 400 }, 'Approve')
]
)
]),
])
);
}
ReactDOM.render(
$(Chart),
document.getElementById("chart")
);
// name the cell section
return "the code";
}
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
d3 = import('d3')
Insert cell
React = import('https://cdn.skypack.dev/react@18.2.0?min')
Insert cell
ReactDOM = import('https://cdn.skypack.dev/react-dom@18.2.0?min')
Insert cell
Scale = import('https://cdn.skypack.dev/@visx/scale@3.3.0?min')
Insert cell
Axis = import('https://cdn.skypack.dev/@visx/axis@3.3.0?min')
Insert cell
Group = import('https://cdn.skypack.dev/@visx/group@3.3.0?min')
Insert cell
Curve = import('https://cdn.skypack.dev/@visx/curve@3.3.0?min')
Insert cell
Shape = import('https://cdn.skypack.dev/@visx/shape@3.3.0?min')
Insert cell
require('esbuild@0.18.12/lib/main.js').catch(() => window["__create"])
Insert cell
Insert cell
esbuild = esbuildExports.reduce((o, x) => {
o[x] = window[x];
return o;
}, {})
Insert cell
esbuild.initialize()
Insert cell

Purpose-built for displays of data

Observable is your go-to platform for exploring data and creating expressive data visualizations. Use reactive JavaScript notebooks for prototyping and a collaborative canvas for visual data exploration and dashboard creation.
Learn more