Published
Edited
Mar 31, 2022
7 stars
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
data = [ // x & y will be overwritten by the simulation
{"x_init":150, "y_init":80, "r":20, "fill":"#990000", "fill_opacity": 0.4},
{"x_init":155, "y_init":85, "r":30, "fill":"#009900", "fill_opacity": 0.4},
{"x_init":160, "y_init":95, "r":35, "fill":"#000099", "fill_opacity": 0.4},
{"x_init":330, "y_init":165, "r":20, "fill":"#009999", "fill_opacity": 0.4},
{"x_init":330, "y_init":165, "r":30, "fill":"#900099", "fill_opacity": 0.4}
];
Insert cell
drawPlot = () => {
console.log('plot')
let points = d3.select("#scatterplot").selectAll("circle").data(data);
let labels = d3.select("#scatterplot").selectAll("text").data(data);
// For new points and labels (not drawn yet, e.g., when page loads), draw them
points.enter().append("circle")
.attr("cx", d => d.x)
.attr("cy", d => d.y)
.attr("r", d => d.r)
.attr("fill", d => d.fill)
.attr("fill-opacity", d => d.fill_opacity);
labels.enter().append("text")
.text(d => d.x_init + ", " + d.y_init)
.attr("x", d => d.x + d.r)
.attr("y", d => d.y)
.attr("alignment-baseline", "middle"); // Vertically align text with point

// For existing points already drawn, update their locations,
// using (updated) values in data
points
.attr("cx", d => d.x)
.attr("cy", d => d.y);
labels
.attr("x", d => d.x + d.r)
.attr("y", d => d.y);
}
Insert cell
viewof sim = {
const sim = d3.forceSimulation(data)
.force("collision", d3.forceCollide(d => d.r)) // Repulsion force
.force("x_force", d3.forceX(d => d.x_init)) // Each point attacted to its center x and y
.force("y_force", d3.forceY(d => d.y_init))
.on('tick', drawPlot) // Redraws scatterplot at every simulation "tick"
.stop();
if (repel) {
sim.force("collision", d3.forceCollide((d) => d.r)); // Add repulsion force back
} else {
sim.force("collision", null); // Removes repulsion force
}

sim.alpha(1); // Alpha value of 1 resets simulation back to beginning
sim.alphaMin(0.5); // Simulation ends quick --> necessary to toggle the checkbox
sim.restart();
return sim;
}
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