Published
Edited
Jun 21, 2022
4 stars
Insert cell
Insert cell
chart = {
const svg = d3.create("svg")
.attr("width", width)
.attr("height", height);

let circles = update(svg, nodes)

let simulation = d3.forceSimulation()
.nodes(nodes)
.force('charge', d3.forceManyBody().strength(defaults.FORCEMANYBODY_STRENGTH))
.force('collision', d3.forceCollide().radius(defaults.COLLISION_RADIUS).strength(defaults.COLLISION_STRENGTH))
.force('center', d3.forceCenter(width/2, height/2).strength(1))
.force('x', d3.forceX(width/2).strength(defaults.XFORCE_STRENGTH))
.force('y', d3.forceY(height/2).strength(defaults.YFORCE_STRENGTH))
.force("cluster", forceCluster().strength(1))
simulation.on('tick', ticked)
simulation.velocityDecay(defaults.VELOCITY_DECAY).alpha(defaults.ALPHA).restart()

function ticked() {
circles
.attr('cx', (d) => d.x)
.attr('cy', (d) => d.y)
}
return svg.node();
}
Insert cell
function centroid(nodes) {
let x = 0;
let y = 0;
let z = 0;
for (const d of nodes) {
let k = d.radius ** 2;
x += d.x * k;
y += d.y * k;
z += k;
}
return {x: x / z, y: y / z};
}
Insert cell
function forceCluster() {
var strength = 0.8;
let nodes;
function force(alpha) {
const centroids = d3.rollup(nodes, centroid, d => d.band);
const l = alpha * strength;
for (const d of nodes) {
const {x: cx, y: cy} = centroids.get(d.band);
d.vx -= (d.x - cx) * l;
d.vy -= (d.y - cy) * l;
}
}
force.initialize = _ => nodes = _;
force.strength = function(_) {
return arguments.length ? (strength = +_, force) : strength;
};
return force;
}
Insert cell
nodes = getData(300, d3.range(1,7), null, defaults.RADIUS)
Insert cell
height = 500
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