Vertical Beeswarm in JavaScript
Using ApexCharts with JavaScript
This Vertical Beeswarm example uses ApexCharts.js directly in JavaScript, with no wrapper component.
Install it with npm install apexcharts, then mount the chart with new ApexCharts(element, options).render().
// A VERTICAL beeswarm: value runs up the Y axis, each species is a column, and
// dots are anti-overlap "swarm" packed so the column's WIDTH reads as density.
// One dot per penguin. Figures are an illustrative sample around the real
// Palmer Archipelago body-mass distributions (Gentoo run visibly heavier).
// Shared by the vanilla-js / React / Vue builds.
var SPECIES = [
{ name: 'Adelie', mean: 3700, sd: 460, n: 44 },
{ name: 'Chinstrap', mean: 3733, sd: 385, n: 34 },
{ name: 'Gentoo', mean: 5076, sd: 505, n: 40 },
]
// Deterministic normal-ish sample (Irwin-Hall of 6 uniforms via an LCG): stable
// across re-renders and SSR, no Math.random. Rounded to the nearest 25 g.
function swarm(mean, sd, n, seed) {
var out = []
var s = seed >>> 0
function u() {
s = (s * 1664525 + 1013904223) >>> 0
return s / 4294967296
}
for (var i = 0; i < n; i++) {
var g = 0
for (var k = 0; k < 6; k++) g += u()
var z = (g - 3) / Math.sqrt(0.5)
out.push(Math.round((mean + z * sd) / 25) * 25)
}
return out
}
var swarmSeries = SPECIES.map(function (sp, i) {
return {
name: sp.name,
data: swarm(sp.mean, sp.sd, sp.n, 97 + i * 613).map(function (v, j) {
return { name: sp.name + ' ' + (j + 1), value: v }
}),
}
})
var options = {
series: swarmSeries,
chart: {
id: 'bodyMassSwarm',
type: 'unit',
height: 460,
fontFamily: 'inherit',
animations: {
enabled: true,
speed: 700,
},
},
colors: ['#eb6834', '#4a3aa7', '#1baf7a'],
legend: {
position: 'bottom',
markers: { radius: 12 },
},
plotOptions: {
unit: {
layout: 'scatter',
size: 4.4,
scatter: {
orientation: 'vertical',
spread: 'swarm',
xMin: 2000,
xMax: 6000,
tickAmount: 5,
xTitle: 'Body mass',
xFormatter: function (v) {
return (v / 1000).toFixed(1) + ' kg'
},
},
},
},
tooltip: {
enabled: true,
},
}
var chart = new ApexCharts(document.querySelector('#chart'), options)
chart.render()