Public
Edited
May 12, 2023
5 forks
20 stars
Insert cell
Insert cell
Insert cell
Insert cell
Plot.plot({
aspectRatio: 0.6,
marginLeft: 90,
width: 1152,
style: `
margin: 0 -14px;
background: #111;
color: #fff;
max-width: none;
text-transform: uppercase;
width: calc(100% + 28px);
`,
x: {domain: d3.range(1, 40), axis: null}, // day of month, aligned by day of week
y: {domain: d3.range(12)}, // month of year
length: {type: "identity"}, // overloading meaning as lunar phase angle!
marks: (({data, x, y, r, hemisphere, projection}) => [
Plot.axisY({textAnchor: "start", tickFormat: Plot.formatMonth(locale, "long"), tickSize: 0, dx: -50}),
Plot.dot(data, {x, y, r, fill: "#333"}),
Plot.text(data, {x, y, r, text: (d) => d.getUTCDate(), dy: -r - 5, fontSize: 7}),
Plot.vector(data, {
x,
y,
length(d) {
const noon = d3.utcHour.offset(d, 12);
const illum = suncalc.getMoonIllumination(noon);
return 180 - illum.phase * 360;
},
shape: {
draw(context, length) {
projection.rotate([length, 0]).scale(r);
const path = d3.geoPath(projection, context);
path(hemisphere);
}
},
anchor: "start", // disable default translate along length
fill: "currentColor"
})
])({
data: (() => {
const start = d3.utcYear(Date.UTC(year, 0, 1));
return d3.utcDays(start, d3.utcYear.offset(start));
})(),
x(d) {
const start = d3.utcMonth(d);
const offset = start.getUTCDay() || 7;
return d.getUTCDate() + offset;
},
y(d) {
return d.getUTCMonth();
},
r: 12,
hemisphere: d3.geoCircle()(),
projection: d3.geoOrthographic().translate([0, 0])
})
})
Insert cell
Insert cell
suncalc = (await import("https://cdn.jsdelivr.net/npm/suncalc@1/+esm")).default
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