Public
Edited
Sep 29, 2023
8 forks
Importers
43 stars
Insert cell
Insert cell
data = {
const random = d3.randomNormal();
return Array.from({ length: width }, random);
}
Insert cell
Plot.plot({
y: { axis: null },
marks: [
beeswarmX(data, { x: (d) => d, y: () => 0, fill: "white", stroke: "black" })
],
height: 200
})
Insert cell
Insert cell
Insert cell
(replay,
Plot.plot({
height: 320,
marks: [
beeswarmX(data, {
x: (d) => d,
r: (d, i) => 1 + 2 * (i % 2),
fill: (d) => d,
gap: 0.5,
ticks: 2,
dynamic: true,
title: (d) => d
})
]
}))
Insert cell
Plot.plot({
x: { axis: null },
y: { axis: null },
marks: [
beeswarmY(data.slice(0, 100), {
y: (d) => d,
x: () => 0,
r: 1,
fill: (d) => d
}),
Plot.frame()
],
width: 50,
inset: 4,
marginRight: 1,
marginBottom: 1
})
Insert cell
function beeswarmX(data, options = {}) {
return beeswarm(data, { ...options, direction: "x" });
}
Insert cell
function beeswarmY(data, options = {}) {
return beeswarm(data, { ...options, direction: "y" });
}
Insert cell
function beeswarm(
data,
{ gap = 1, ticks = 50, dynamic, direction, xStrength = 0.8, yStrength = 0.05, ...options }
) {
const dots = Plot.dot(data, options);
const { render } = dots;

dots.render = function () {
const g = render.apply(this, arguments);
const circles = d3.select(g).selectAll("circle");

const nodes = [];
const [cx, cy, x, y, forceX, forceY] =
direction === "x"
? ["cx", "cy", "x", "y", d3.forceX, d3.forceY]
: ["cy", "cx", "y", "x", d3.forceY, d3.forceX];
for (const c of circles) {
const node = {
x: +c.getAttribute(cx),
y: +c.getAttribute(cy),
r: +c.getAttribute("r")
};
nodes.push(node);
}
const force = d3
.forceSimulation(nodes)
.force("x", forceX((d) => d[x]).strength(xStrength))
.force("y", forceY((d) => d[y]).strength(yStrength))
.force(
"collide",
d3
.forceCollide()
.radius((d) => d.r + gap)
.iterations(3)
)
.tick(ticks)
.stop();
update();
if (dynamic) force.on("tick", update).restart();
return g;

function update() {
circles.attr(cx, (_, i) => nodes[i].x).attr(cy, (_, i) => nodes[i].y);
}
};

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