Public
Edited
Aug 31, 2023
1 fork
Insert cell
Insert cell
Insert cell
Insert cell
canvasContext = {
const context = DOM.context2d(width, height);
const canvas = context.canvas;

let circles = d3.range(number_of_circles).map((i) => ({
x: Math.random() * (width - radius * 2) + radius,
y: Math.random() * (height - radius * 2) + radius,
color: colors[i % 10]
}));
let simulation = d3
.forceSimulation(circles)
//.force("center", d3.forceCenter(width / 2, height / 2))
.force("collision", d3.forceCollide(10).radius(radius * 3))
.force("center", forceBoundary(20, 20, width - 20, height - 20).border(0))

.on("tick", render);

context.clearRect(0, 0, width, height);
// Set up to compute a Delaunay triangulation from the circles
function render() {
console.log(circles[0].vx );
context.clearRect(0, 0, width, height);
const voronoi = d3.Delaunay.from(
circles,
(d) => d.x,
(d) => d.y
).voronoi([0, 0, width, height]);

// Draw the voronoi mesh
context.strokeStyle = "#ccc";
context.lineWidth = 1;
context.beginPath();
voronoi.render(context);
context.fillStyle = context.stroke();
// Draw the circles
// for (const { x, y, color, active } of circles) {
// context.beginPath();
// context.moveTo(x + radius, y);
// context.arc(x, y, radius, 0, Math.PI * 2);
// context.fillStyle = color;
// context.fill();
// if (active) {
// context.strokeStyle = "black";
// context.lineWidth = 1;
// context.stroke();
// }
// }
}

const dragBehavior = drag(simulation, circles);

d3.select(canvas).call(dragBehavior);

render();
return canvas;
}
Insert cell
function drag(simulation, circles) {
// Find the circle that is closest to my mouse
function dragSubject(event) {
// must be re-initialized again whenever drag happens, because dragging changes the original data
const quadCircles = d3
.quadtree()
.x((d) => d.x)
.y((d) => d.y)
.addAll(circles);

return quadCircles.find(event.x, event.y, 40);
}

// raise the chosen subject
function dragStart(event) {
simulation.alphaTarget(1).restart();
const subject = event.subject;

subject.fx = subject.x;
subject.fy = subject.y;
subject.active = true;
}

function drag(event) {
event.subject.fx = event.x;
event.subject.fy = event.y;
}

// change the style of the dragged circle back to normal
function dragEnd(event) {
event.subject.fx = null;
event.subject.fy = null;
event.subject.active = false;

simulation.alphaTarget(0);
}

return d3
.drag()
.subject(dragSubject)
.on("start", dragStart)
.on("drag", drag)
.on("end", dragEnd);
}
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