Public
Edited
Oct 24, 2023
5 forks
Importers
60 stars
Insert cell
Insert cell
Insert cell
spiral = Array.from({ length: 76 }, (_, i) => [
(Math.PI / 3) * i, // angle (in radians)
2 * i // radius
])
Insert cell
Insert cell
d3.lineRadial()(spiral)
Insert cell
Insert cell
svg`<svg width=300 height=300><path d="${d3.lineRadial()(
spiral
)}" fill="none" stroke="black" transform="translate(150,150)"></svg>`
Insert cell
Insert cell
{
const width = 300,
context = DOM.context2d(width, width);

const step = (Math.PI * (-10 + ((now / 2000) % 20))) / 20;

const spiral = Array.from({ length: 76 }, (_, i) => [step * i, 2 * i]);

context.save();
context.translate(width / 2, width / 2);

context.beginPath();
d3.lineRadial().context(context)(spiral);
context.stroke();

context.restore(); // undo translate

return context.canvas;
}
Insert cell
Insert cell
spiral2 = {
const length = 76,
spiral = d3
.lineRadial()
.angle((d, i) => (Math.PI / 4) * i) // d is empty (and ignored), i is the index
.radius((d, i) => (length - i) * 2);

return spiral({ length });
}
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
yearly = d3
.scaleLinear()
.domain([1, 12 + 1]) // 🌶 we add 1, otherwise December is superposed with January
.range([0, 2 * Math.PI])
Insert cell
Insert cell
data = FileAttachment("ice-sheets.csv").csv({typed: true})
.then(data =>
data.sort(
(a, b) => d3.ascending(+a.year, +b.year) || d3.ascending(+a.mo, +b.mo)
)
)
Insert cell
Insert cell
scaleRadius = d3.scaleLinear()
.domain([0, d3.max(data, d => d.extent)])
.range([0, 270])
Insert cell
radial = d3.lineRadial()
.angle(d => yearly(d.mo))
.radius(d => scaleRadius(d.extent))
.curve(d3.curveCatmullRomOpen)
.defined(d => d.extent > 0) // two months have no data, represented by extent=-9999
Insert cell
Insert cell
{
const svg = d3
.create("svg")
.attr("viewBox", [0, 0, 700, 500])
.style("max-width", "700px"),
g = svg.append("g").attr("transform", "translate(400,250)");

g.selectAll("path")
.data(["S", "N"])
.join("path")
.attr("fill", "none")
.attr("stroke", "black")
.attr("stroke-width", "0.2")
.attr("d", region => radial(data.filter(d => d.region === region)));

return svg.node();
}
Insert cell
Insert cell
Insert cell
Insert cell
{
const length = (3 + ((now / 1500) % 8)) | 0;
const polygon = d3
.radialLine()
.angle((_, i) => (i / length) * 2 * Math.PI)
.curve(d3.curveLinearClosed)
.radius(() => 150),
path = polygon({ length });
return svg`<svg width=300 height=300>
<path d="${path}" fill="none" stroke="black" transform="translate(150,150)">
</svg>`;
}
Insert cell
Insert cell
function polygon(sides) {
var length = sides,
s = 1,
phase = 0;
const radial = d3
.lineRadial()
.curve(d3.curveLinearClosed)
.angle((_, i) => (i / length) * 2 * Math.PI + phase)
.radius(() => s);
const poly = function() {
return radial(Array.from({ length }));
};
poly.context = function(_) {
return arguments.length ? (radial.context(_), poly) : radial.context();
};
poly.n = function(_) {
return arguments.length ? ((length = +_), poly) : length;
};
poly.rotate = function(_) {
return arguments.length ? ((phase = +_), poly) : phase;
};
poly.scale = function(_) {
return arguments.length ? ((s = +_), poly) : s;
};
poly.curve = function(_) {
return arguments.length ? (radial.curve(_), poly) : radial.curve();
};
poly.radius = radial.radius;
poly.angle = radial.angle;
return poly;
}
Insert cell
Insert cell
polygon(6).scale(10)()
Insert cell
svg`<svg width=300 height=300><path
d="${
polygon((3 + ((now / 1500) % 8)) | 0) .scale(150) .rotate(now / 4000)()
}"
fill="none" stroke="black" transform="translate(150,150)"></svg>`
Insert cell
{
const width = 300,
context = DOM.context2d(width, width),
p = polygon()
.context(context)
.scale(width / 2 - 2);
context.translate(width / 2, width / 2);

do {
context.beginPath();
p.n(3 + ((Date.now() / 1500) % 4 | 0))();
context.stroke();
yield context.canvas;
context.fillStyle = "rgba(255,255,255,0.1)";
context.fillRect(-width / 2, -width / 2, width, width);
context.rotate(0.01);
} while (true);
}
Insert cell
Insert cell
svg`<svg width=300 height=300><path d="${

polygon()
.curve(d3.curveCardinalClosed)
.scale(148)
.n(
(3 + ((now / 1500) % 5)) | 0
)()

}" fill="none" stroke="black" transform="translate(150,150)"></svg>`
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