Public
Edited
Oct 2, 2024
Insert cell
Insert cell
Insert cell
Insert cell
viewof strokeWidth = Inputs.range([0,5])
Insert cell
{
// viewof strokeWidth.value = now/1000 * 2 % 5
// viewof strokeWidth.dispatchEvent(new CustomEvent('input'))
// return now
}
Insert cell
svg = {
const svg = d3
.create("svg")
.attr("width", size.width)
.attr("height", size.height)
.attr("viewBox", [0, 0, size.width, size.height])
.attr(
"style",
"max-width: 100%; height: auto; height: intrinsic;border: solid 1px"
);

const curves = svg
.append("g")
.attr("fill", "none")
.attr("stroke", "black")
.attr("stroke-width", strokeWidth);
curves.append("path");
function updateCurve() {
curves.select("path").attr("d", drawCurves(d3.path(), initialPoints));
svg
.selectAll("circle")
.data(initialPoints)
.attr("cx", (d) => d.x)
.attr("cy", (d) => d.y);
}
const newCircle = null;
svg.call(
d3
.drag()
.subject((e, d) => {
const r = { x: e.x, y: e.y };
initialPoints.push(r);
return r;
})
.on("start", (e) => {
newCircle = svg
.selectAll("circle")
.data(initialPoints)
.enter()
.append("circle")
.attr("r", "5")
.attr("cx", e.x)
.attr("cy", e.y)
.call(addDrag);
updateCurve();
})
.on("drag", (e) => {
e.subject.x = e.x;
e.subject.y = e.y;
updateCurve();
})
.on("end", (e) => {
// newCircle = null
})
);

function addDrag(selection) {
selection.call(
d3
.drag()
.on("start", (e) => {})
.on("drag", function (e) {
e.subject.x = e.x;
e.subject.y = e.y;
d3.select(this)
.attr("cx", (d) => d.x)
.attr("cy", (d) => d.y);
updateCurve();
})
);
}
svg
.selectAll("circle")
.data(initialPoints)
.join("circle")
.attr("r", "5")
.attr("cx", (d) => d.x)
.attr("cy", (d) => d.y)
.call(addDrag);

updateCurve();
return svg;
}
Insert cell
initialPoints = {
const getRandomY = d3.randomUniform(size.height / 5, size.height * 0.8);
return d3
.range(1, 5)
.map((it) => ({ x: size.width * it * 0.2, y: getRandomY() }));
}
Insert cell
function drawCurve(ctx, p1, p2){
ctx.moveTo(p1.x, p1.y)
const midx = (p1.x+p2.x)/2
ctx.bezierCurveTo(midx, p1.y, midx, p2.y, p2.x, p2.y)
return ctx
}
Insert cell
function drawCurves(ctx, points){
if (!points || points.length < 2) return
ctx.moveTo(points[0].x, points[0].y)
for (let i = 1; i < points.length; i++){
const midx = (points[i-1].x+points[i].x)/2
ctx.bezierCurveTo(midx, points[i-1].y, midx, points[i].y, points[i].x, points[i].y)
}
return ctx
}
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