Published unlisted
Edited
Feb 21, 2022
Insert cell
Insert cell
{
const height = 400;
const curve = bumpRadial;

const svg = d3
.create("svg")
.attr("viewBox", [-width / 2, -height / 2, width, height]);

const points = [
[0, 100],
[Math.PI / 3, 150],
[Math.PI * (2 / 3), 150],
[Math.PI * (3 / 3), 150],
[Math.PI * (4 / 3), 20],
[Math.PI * (5 / 3), 170],
[Math.PI * (6 / 3), 100]
];
const p = d3.lineRadial();

svg
.append("path")
.attr("fill", "none")
.attr("stroke", "brown")
.attr("d", p(points));

svg
.append("path")
.attr("fill", "none")
.attr("stroke", "#333")
.attr(
"d",
p.curve(curve)(
points.map(([x, y]) => [Math.atan2(x, -y), Math.hypot(x, y)])
)
);

return svg.node();
}
Insert cell
class BumpRadial {
constructor(context) {
this._context = context;
}
lineStart() {
this._point = 0;
}
lineEnd() {}
point(x, y) {
(x = +x), (y = +y);
if (this._point++ > 0) {
const p0 = pointRadial(this._x0, this._y0);
const p1 = pointRadial(this._x0, (this._y0 = (this._y0 + y) / 2));
const p2 = pointRadial(x, this._y0);
const p3 = pointRadial(x, y);
this._context.moveTo(...p0);
this._context.bezierCurveTo(...p1, ...p2, ...p3);
}
this._x0 = x;
this._y0 = y;
}
}
Insert cell
function bumpRadial(context) {
return new BumpRadial(context);
}
Insert cell
pointRadial = d3.pointRadial
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