Scatter with Jitter in JavaScript

Using ApexCharts with JavaScript

This Scatter with Jitter 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().

JavaScript installation guide
// ── Reproducible synthetic data (seeded PRNG, no network) ──────────────
function mulberry32(a) {
  return function () {
    a |= 0
    a = (a + 0x6d2b79f5) | 0
    var t = Math.imul(a ^ (a >>> 15), 1 | a)
    t = (t + Math.imul(t ^ (t >>> 7), 61 | t)) ^ t
    return ((t ^ (t >>> 14)) >>> 0) / 4294967296
  }
}
var rng = mulberry32(20240607)

function gauss(mean, sd) {
  var u = 0,
    v = 0
  while (u === 0) u = rng()
  while (v === 0) v = rng()
  return mean + sd * Math.sqrt(-2 * Math.log(u)) * Math.cos(2 * Math.PI * v)
}

// Individual API response-time readings per data-centre region. Compact
// strip-plot form: { x: 'Region', y: [reading, reading, ...] }. Every reading
// becomes its own hoverable marker, scattered horizontally within its band.
var REGIONS = [
  { name: 'Frankfurt', mean: 120, sd: 22 },
  { name: 'Mumbai', mean: 182, sd: 30 },
  { name: 'Oregon', mean: 96, sd: 18 },
  { name: 'Singapore', mean: 158, sd: 26 },
  { name: 'Virginia', mean: 82, sd: 16 },
]

function readings(region) {
  var out = []
  for (var i = 0; i < 150; i++) {
    out.push(Math.max(20, Math.round(gauss(region.mean, region.sd))))
  }
  return out
}

var options = {
  series: [
    {
      name: 'Frankfurt',
      data: [{ x: 'Frankfurt', y: readings(REGIONS[0]) }],
    },
    {
      name: 'Mumbai',
      data: [{ x: 'Mumbai', y: readings(REGIONS[1]) }],
    },
    {
      name: 'Oregon',
      data: [{ x: 'Oregon', y: readings(REGIONS[2]) }],
    },
    {
      name: 'Singapore',
      data: [{ x: 'Singapore', y: readings(REGIONS[3]) }],
    },
    {
      name: 'Virginia',
      data: [{ x: 'Virginia', y: readings(REGIONS[4]) }],
    },
  ],
  chart: {
    type: 'scatter',
    height: 460,
  },
  title: {
    text: 'API response time by region',
    align: 'center',
  },
  plotOptions: {
    scatter: {
      // Spread the readings in each band horizontally (axis units; 1 = one
      // band step). Set `distributed: true` to colour each band differently.
      jitter: {
        enabled: true,
        x: 0.35,
      },
    },
  },
  markers: {
    size: 3,
    strokeWidth: 0,
  },
  fill: {
    opacity: 0.6,
  },
  legend: { show: false },
  xaxis: {
    // strip plots read better without the vertical crosshair line
    crosshairs: { show: false },
  },
  yaxis: {
    title: { text: 'Response time (ms)' },
    labels: {
      formatter: function (v) {
        return Math.round(v)
      },
    },
  },
  tooltip: {
    // anchor the tooltip to the hovered band so it stays put instead of
    // chasing each individual marker
    shared: true,
    intersect: false,
    y: {
      formatter: function (v) {
        return Math.round(v) + ' ms'
      },
    },
  },
}

var chart = new ApexCharts(document.querySelector('#chart'), options)
chart.render()