canvas = {
const context = DOM.context2d(width, height);
const numNodes = 4000,
mbStrength = -15,
centerX = width / 2,
centerY = height / 2,
strength = 0.1;
var nodes = d3.range(numNodes).map(function (i) {
return {
id: i,
r: 3
};
});
var forceRadial = d3
.forceRadial(
function (d) {
return radiusFactor * ((d.id % 4) + 1) + centerClusterGap;
},
centerX,
centerY
)
.strength(1);
var forceManybody = d3.forceManyBody().strength(mbStrength);
var forceCenter = d3.forceCenter(centerX, centerY);
var forceCollide = d3
.forceCollide(function (d) {
return d.r + 0.5;
})
.iterations(2)
.strength(strength);
var simulation = d3
.forceSimulation(nodes)
.velocityDecay(0.2)
.force("x", d3.forceX(centerX).strength(0.2))
.force("y", d3.forceY(centerY).strength(0.2))
.force("collide", forceCollide)
.force("center", forceCenter)
.force("n-body", forceManybody)
.force("radial", forceRadial)
.on("tick", ticked);
while (simulation.alpha() > 0.01) {
simulation.tick();
}
function ticked() {
context.clearRect(0, 0, width, height);
context.save();
nodes.forEach(function (d, i) {
context.beginPath();
context.moveTo(d.x + d.r, d.y);
context.arc(d.x, d.y, d.r, 0, 2 * Math.PI);
context.fillStyle = getColor(d.id);
context.fill();
});
context.restore();
}
function getColor(id) {
const ring = id % 4;
if (ring === 0) return "#48EBCC";
if (ring === 1) return "#60968C";
if (ring === 2) return "#8D49EB";
if (ring === 3) return "#EB7549";
}
simulation.alpha(1).restart();
return context.canvas;
}