Published
Edited
Nov 20, 2020
Importers
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
clerp = ([x0, y0], [x1, y1], t) =>
[x0*(1-t) + x1*t, y0*(1-t) + y1*t]
Insert cell
circle_interp = (a, m, b) => {
const
b_m = csub(b, m),
m_a = csub(m,a),
ab_m = cmul(a, b_m),
bm_a = cmul(b, m_a);
return (t) => cdiv(
clerp(ab_m, bm_a, t),
clerp(b_m, m_a, t));
}
Insert cell
plotarc = () => {
let update;
const
height = 500,
p1 = [width / 5, 200],
p2 = [width / 3, 100],
p3 = [2 * width / 3, 350],
svg = d3.select(DOM.svg(width, height)),

arc = svg.append("path")
.attr("fill", "none")
.attr("stroke-width", "2px")
.attr("stroke", "#79e"),

small_points = svg.append("g")
.selectAll("circle")
.data(Array.from(Array(33), (_,i) => i/32))
.enter().append("circle")
.attr("fill", "#c38")
.attr("r", 3),

point = svg.append("g")
.attr("cursor", "move")
.attr("pointer-events", "all")
.attr("stroke", "transparent")
.attr("stroke-width", 30)
.selectAll("circle")
.data([p1, p2, p3])
.enter().append("circle")
.attr("r", 7)
.attr("fill", "#26b")
.call(d3.drag()
.subject(([x, y]) => ({x, y}))
.on("drag", (d) => {
d[0] = clamp(5, width-5, d3.event.x);
d[1] = clamp(5, height-5, d3.event.y);
update();
}));
update = function update() {
const
parametric_arc = circle_interp(p1, p2, p3),
arc_path = bezpts_to_svgpath(bezeval(
parametric_arc, [0,1], [0,width, 0, height], 0.1));
arc.attr("d", arc_path);
point
.attr("cx", d => d[0])
.attr("cy", d => d[1]);
small_points
.attr("cx", t => parametric_arc(t)[0])
.attr("cy", t => parametric_arc(t)[1]);
}
update();
return svg.node();
}
Insert cell
clamp = (a, b, x) => Math.max(a, Math.min(x, b))
Insert cell
Insert cell
Insert cell
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