Public
Edited
Jul 26, 2023
Insert cell
Insert cell
beeswarm = beeswarmForce()
.x((d) => x(d.xV))
.y((d) => x(d.yV))
.r((d) => 1 + r(d.size))
Insert cell
{
const svg = d3
.create("svg")
.attr("width", chartwidth + margin.left + margin.right)
.attr("height", chartheight + margin.top + margin.bottom);

const g = svg
.append("g")
.attr("transform", `translate(${[margin.left, margin.top]})`);

g.append("g")
.call(d3.axisBottom(x).tickSizeOuter(0))
.attr("transform", `translate(0, ${chartheight / 1.25})`);

g.selectAll("circle")
.data(beeswarm(data))
.join("circle")
.attr("stroke", "black")
.attr("fill-opacity", 0.8)
.attr("cx", (d) => d.x)
.attr("cy", (d) => d.y)
.attr("r", (d) => r(d.data.size));

return svg.node();
}
Insert cell
x = d3.scaleLinear(
d3.extent(data, (d) => d.xV),
[0, chartwidth]
)
Insert cell
y = d3.scaleLinear(
d3.extent(data, (d) => d.yV),
[0, height]
)
Insert cell
r = d3.scaleSqrt(
[100, 1000],
[1, Math.sqrt(width * height) / 30]
);
Insert cell
margin = ({ left: 2 * r.range()[1], right: 2 * r.range()[1], top: 1, bottom: 1 });
Insert cell
chartwidth = width - margin.left - margin.right;
Insert cell
height = 400
Insert cell
chartheight = height - margin.top - margin.bottom;
Insert cell
// Make some random data
data = {
const random = d3.randomNormal();
return Array.from({ length: 100 }).map((d) => ({
xV: random(),
yV: random(),
size: d3.randomUniform(...r.domain())()
}));
}
Insert cell
beeswarmForce = function () {
let x = (d) => d[0];
let y = (d) => d[1];
let r = (d) => d[2];
let ticks = 300;

function beeswarm(data) {
const entries = data.map((d) => {
return {
x0: typeof x === "function" ? x(d) : x,
y0: typeof y === "function" ? y(d) : y,
r: typeof r === "function" ? r(d) : r,
data: d
};
});

const simulation = d3
.forceSimulation(entries)
.force(
"x",
d3.forceX((d) => d.x0)
)
.force(
"y",
d3.forceY((d) => d.y0)
)
.force(
"collide",
d3.forceCollide((d) => d.r)
);

for (let i = 0; i < ticks; i++) simulation.tick();

return entries;
}

beeswarm.x = (f) => (f ? ((x = f), beeswarm) : x);
beeswarm.y = (f) => (f ? ((y = f), beeswarm) : y);
beeswarm.r = (f) => (f ? ((r = f), beeswarm) : r);
beeswarm.ticks = (n) => (n ? ((ticks = n), beeswarm) : ticks);

return beeswarm;
}
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