// Raw observations per group (Box-Muller Gaussian; Math.random is seeded by
// the sample template).
function sample(mean, sd, n) {
var points = []
for (var k = 0; k < n; k++) {
var u1 = Math.random(),
u2 = Math.random()
var g = Math.sqrt(-2 * Math.log(u1)) * Math.cos(2 * Math.PI * u2)
points.push(Math.round((mean + g * sd) * 10) / 10)
}
return points
}
// Each layout is a complete plotOptions.violin spec, so switching between
// them never leaves a leaf from the previous layout behind. Hidden layers
// hand their lane back to the cloud automatically.
var RAINCLOUD_LAYOUTS = {
classic: {
side: 'right',
box: { show: true },
points: { show: true, position: 'left' },
},
'cloud-rain': {
side: 'right',
box: { show: false },
points: { show: true, position: 'left' },
},
'cloud-box': {
side: 'right',
box: { show: true },
points: { show: false, position: 'left' },
},
overlay: {
side: 'both',
box: { show: true },
points: { show: true, position: 'center', constrainToViolin: true },
},
}
var options = {
series: [
{
name: 'Measurement',
data: [
{ x: 'North', points: sample(52, 9, 160) },
{ x: 'East', points: sample(61, 6, 160) },
{ x: 'South', points: sample(47, 12, 160) },
],
},
],
chart: {
id: 'raincloudVariations',
type: 'raincloud',
height: 420,
},
colors: ['#14b8a6'],
title: {
text: 'One distribution chart, four layouts',
align: 'left',
},
yaxis: {
title: {
text: 'Measurement',
},
},
}
var chart = new ApexCharts(document.querySelector('#chart'), options)
chart.render()
// RAINCLOUD_LAYOUTS lives in the shared head script.
var layoutButtons = Array.prototype.slice.call(
document.querySelectorAll('.controls button[data-layout]'),
)
layoutButtons.forEach(function (btn) {
btn.addEventListener('click', function () {
layoutButtons.forEach(function (b) {
b.classList.remove('active')
})
btn.classList.add('active')
chart.updateOptions({
plotOptions: {
violin: RAINCLOUD_LAYOUTS[btn.getAttribute('data-layout')],
},
})
})
})