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();
}