Public
Edited
Mar 10, 2024
Paused
2 forks
45 stars
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Plot.plot({
marks: [
Plot.rectY(data, { x1: "year", x2: (d) => d.year + 5, y: "wheat" }),
Plot.areaY(data, {
x: "year",
y: "wages",
fill: "rgb(205,215,210)"
})
]
})
Insert cell
Insert cell
Plot.plot({
marks: [
Plot.rectY(data, {
x1: "year",
x2: (d) => (d.year === 1820 ? 1821 : d.year + 5), // 1820 data only extends to 1821
y: "wheat"
}),
Plot.areaY(data, {
filter: (d) => d.year <= 1810, // Prevent the absent data beyond 1810 being treated as 0s.
x: "year",
y: "wages",
fill: "rgb(205,215,210)"
})
]
})
Insert cell
Insert cell
Insert cell
{
const gradientFill = () =>
htl.svg`<defs>
<linearGradient id="gradient1" gradientUnits="${gradientUnits}" gradientTransform="rotate(90)">
<stop offset="25%" stop-color="rgb(0,0,0)" />
<stop offset="50%" stop-color="white" />
</linearGradient>
</defs>`;

return Plot.plot({
marks: [
gradientFill, // Add the SVG gradient definition as (inivisble) mark
Plot.rectY(data, {
x1: "year",
x2: (d) => (d.year === 1820 ? 1821 : d.year + 5),
y: "wheat",
fill: "url(#gradient1)" // Here we link to that invisible gradient definition mark
})
]
});
}
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
barsAndArea = [
() =>
htl.svg`<defs>
<linearGradient id="vFade" gradientUnits="userSpaceOnUse" gradientTransform="rotate(90)">
<stop offset="25%" stop-color="rgb(0,0,0)" />
<stop offset="40%" stop-color="${bgClr}" />
</linearGradient>
</defs>`,

Plot.rectY(data, {
x1: "year",
x2: (d) => (d.year === 1820 ? 1821 : d.year + 5),
y: "wheat",
fill: "url(#vFade)"
}),
Plot.line(data, {
x: "year",
y: "wages",
strokeWidth: 6,
strokeLinecap: "butt",
stroke: "rgb(204,78,91)"
}),
Plot.areaY(data, {
filter: (d) => d.year <= 1810,
x: "year",
y: "wages",
fill: "rgb(205,215,210)"
}),
Plot.line(data, { x: "year", y: "wages", strokeLinecap: "butt" })
]
Insert cell
Plot.plot({
width: w,
height: h,
margin: margin,
style: `background:${bgClr}`,
marks: barsAndArea
})
Insert cell
Insert cell
xAxis = ({
tickFormat: (d) => d3.format("d")(d % 50 === 0 ? d : d % 100),
tickSize: 0,
tickSpacing: 30,
tickPadding: 4,
label: `5 Years each division${" ".repeat(100)}5 Years each division`,
labelAnchor: "center",
labelArrow: "none",
labelOffset: 24
})
Insert cell
Insert cell
yAxes = [
Plot.axisY({
anchor: "right",
tickFormat: (d) =>
d === 0 || d > 100
? ""
: d === 5 || d === 50 || d === 100
? `${d} Shillings`
: d,
tickSize: 0,
tickSpacing: 20,
tickPadding: 4,
fontSize: 7,
labelArrow: "none",
labelOffset: 30,
labelAnchor: "center",
label: `Price of the Quarter ${" ".repeat(25)} of Wheat in Shillings`
}),
Plot.axisY({
anchor: "left",
tickFormat: (d) => (d === 0 || d > 100 ? "" : d % 10 === 0 ? d : 5),
tickSize: 0,
tickSpacing: 20,
tickPadding: 4,
fontSize: 7
})
]
Insert cell
Plot.plot({
width: w,
height: h,
margin: margin,
style: `background:${bgClr}`,
x: xAxis,
marks: [barsAndArea, yAxes].flat()
})
Insert cell
Insert cell
grid = [
Plot.gridX(d3.range(1600, 1830, 50), {
y1: 0,
y2: 100,
strokeWidth: 1.5,
strokeOpacity: 1
}),
Plot.gridX(d3.range(1565, 1830, 5), {
y1: 0,
y2: 100,
strokeWidth: 0.2,
strokeOpacity: 1
}),
Plot.gridY(d3.range(0, 101, 10), { strokeWidth: 2, strokeOpacity: 1 }),
Plot.gridY(d3.range(5, 90, 10), { strokeWidth: 0.2, strokeOpacity: 1 })
]
Insert cell
Plot.plot({
width: w,
height: h,
margin: margin,
style: `background:${bgClr}`,
x: xAxis,
marks: [barsAndArea, yAxes, grid].flat()
})
Insert cell
Insert cell
titlePanel = [
// x and y are the horiztonal and vertical scale functions
(_, { x, y }) =>
htl.svg`
<ellipse cx="${x(1653)}" cy="${y(70)}" rx="${x(1690) - x(1653)}" ry="${
y(53.7) - y(70)
}" stroke-width=4 stroke="black" />
<ellipse cx="${x(1653)}" cy="${y(70)}" rx="${x(1690.8) - x(1653)}" ry="${
y(54) - y(70)
}" fill="${bgClr}" stroke="black" />`
]
Insert cell
Plot.plot({
width: w,
height: h,
margin: margin,
style: `background:${bgClr}`,
x: xAxis,
marks: [barsAndArea, yAxes, grid, titlePanel].flat()
})
Insert cell
Insert cell
Insert cell
monarchData = [
{ name: "Elizabeth", start: 1565, end: 1603 },
{ name: "James I", start: 1603, end: 1625 },
{ name: "Charles I", start: 1625, end: 1649 },
{ name: "Cromwell", start: 1649, end: 1660, commonwealth: true },
{ name: "Charles II", start: 1660, end: 1685 },
{ name: "James II", start: 1685, end: 1689 },
{ name: "William\nand\nMary", start: 1689, end: 1702 },
{ name: "Anne", start: 1702, end: 1714 },
{ name: "George I", start: 1714, end: 1727 },
{ name: "George II", start: 1727, end: 1760 },
{ name: "George III", start: 1760, end: 1820 },
{ name: "George IV", start: 1811, end: 1821 },
{ name: "", start: 1821, end: 1830, future: true }
].map((d, i) => ({
...d,
x: d.start + (d.end - d.start) / 2,
y: (d.future || (!d.commonwealth && i % 2) ? -1 : 1) + 96
}))
Insert cell
Insert cell
monarchs = [
Plot.rect(monarchData, {
x1: "start",
x2: "end",
y1: "y",
y2: (d) => d.y + 1.0,
fill: (d) => (d.commonwealth || d.future ? bgClr : "black"),
stroke: "black"
}),
Plot.ruleX(monarchData, {
x: "end",
y1: (d) => (d.y < 96 ? d.y : d.y + 1),
y2: (d) =>
d.end > 1800 || d.name === "Charles I" || d.commonwealth
? d.y
: d.y < 96
? d.y + 3
: d.y - 2
}),
Plot.text(monarchData, {
x: "x",
y: "y",
fontSize: 9,
textAnchor: "middle",
lineAnchor: "top",
lineHeight: 0.82, // For more compact 'William and Mary' (thanks @Fil)
dy: 4,
text: "name"
})
]
Insert cell
Plot.plot({ height: 45, axis: null, y: { domain: [90, 100] }, marks: monarchs })
Insert cell
Insert cell
<link href="https://fonts.googleapis.com/css2?family=Old+Standard+TT:ital,wght@0,700;1,400&family=Pinyon+Script&family=Fredericka+the+Great&display=swap" rel="stylesheet">
Insert cell
Insert cell
fnt = ({
script: "Pinyon Script",
serif: "Old Standard TT",
display: "Fredericka The Great"
})
Insert cell
Insert cell
Plot.plot({
width: w,
height: h,
margin: margin,
style: `background:${bgClr}; font-family: ${fnt.script}; font-weight:900;`,
x: xAxis,
marks: [barsAndArea, yAxes, grid, monarchs, titlePanel].flat()
})
Insert cell
Insert cell
cCurves = {
const [cx, cy1, cy2] = [
[
1565, 1590, 1600, 1605, 1650, 1695, 1700, 1705, 1750, 1795, 1800, 1805,
1810, 1830
],
[108, 102, 100, 101, 108, 101, 100, 101, 108, 101, 100, 102, 103.5, 108],
[107, 102, 100, 101, 107, 101, 100, 101, 107, 101, 100, 102, 103.5, 107]
];
return cx.map((d, i) => ({ year: cx[i], y1: cy1[i], y2: cy2[i] }));
}
Insert cell
Insert cell
century = {
const centData = [1575, 1650, 1750, 1820].map((d, i) => ({
x: d,
y: 102,
cent: 16 + i + "ᵗʰ Century"
}));
return [
Plot.areaY(cCurves, {
x: "year",
y: "y1",
y2: "y2",
curve: "monotone-x",
stroke: "black",
fill: "black",
strokeWidth: 2
}),
Plot.text(centData, {
x: "x",
y: "y",
text: "cent",
fontFamily: fnt.serif
}),
Plot.frame({ anchor: "left", strokeWidth: 2 }),
Plot.frame({ anchor: "right", strokeWidth: 2 })
];
}
Insert cell
Plot.plot({ width: 900, height: 70, axis: null, margin: 15, marks: century })
Insert cell
Insert cell
annotation = {
return [
Plot.text(["Weekly Wages of a Good Mechanic"], {
x: 1626,
y: 8.4,
rotate: -1.3
}),
Plot.text(["Weekly Wages"], { x: 1741, y: 16.5, rotate: -7 }),
Plot.text(["of a Good Mechanic"], { x: 1762, y: 19.6, rotate: -12 }),
Plot.text(["№1"], {
x: 1700,
y: 105,
fontFamily: fnt.serif,
fontSize: 20
}),
Plot.text(["CHART"], {
x: 1652,
y: 81.5,
fontFamily: fnt.display,
fontSize: 20
}),
Plot.text(["Shewing at One View\nThe Price of The Quarter of Wheat,"], {
x: 1652,
y: 75,
fontSize: 17
}),
Plot.text(["& Wages of Labour by the Week,"], {
x: 1652,
y: 68.5,
fontFamily: fnt.serif,
fontSize: 12
}),
Plot.text(["— from —"], {
x: 1652,
y: 66,
fontFamily: fnt.serif,
fontSize: 8
}),
Plot.text(["The Year 1565 to 1821,"], {
x: 1652,
y: 63.5,
fontSize: 14
}),
Plot.text(["— by —"], {
x: 1652,
y: 60.5,
fontFamily: fnt.serif,
fontSize: 8
}),
Plot.text(["WILLIAM PLAYFAIR,"], {
x: 1652,
y: 57.75,
fontFamily: fnt.display,
fontSize: 12
}),
Plot.text(
["For a Particular Explanation, See Letter to the Lords & Commons"],
{ x: 1700, y: 0, dy: 40 }
)
];
}
Insert cell
Insert cell
final = Plot.plot({
width: w,
height: h,
margin: margin,
style: `background:${bgClr}; font-family: ${fnt.script};`,
x: xAxis,
marks: [
barsAndArea,
yAxes,
grid,
monarchs,
century,
titlePanel,
annotation
].flat()
})
Insert cell
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