Metrics by Unit in JavaScript
Using ApexCharts with JavaScript
This Metrics by Unit 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().
// Three metrics in three units: dollars, percent, people. They cannot share
// an axis, and a dual-axis chart is the most misread chart there is. The
// 2-D answer: rows = metric, columns = business unit, and
// `scales.y: 'independent-row'` gives each METRIC one shared domain across
// its row. Along a row the units are directly comparable (identical ticks);
// across rows each metric keeps its own honest scale.
//
// Deterministic monthly walks so the e2e snapshot is stable.
function mulberry32(seed) {
return function () {
seed |= 0
seed = (seed + 0x6d2b79f5) | 0
var t = Math.imul(seed ^ (seed >>> 15), 1 | seed)
t = (t + Math.imul(t ^ (t >>> 7), 61 | t)) ^ t
return ((t ^ (t >>> 14)) >>> 0) / 4294967296
}
}
function monthly(seed, base, drift, vol) {
var rand = mulberry32(seed)
var out = []
var ts = new Date('01 Jan 2025').getTime()
var val = base
for (var i = 0; i < 12; i++) {
val = Math.max(1, val + drift + (rand() - 0.5) * vol)
out.push([ts, Math.round(val * 10) / 10])
ts += 2678400000 // ~1 month
}
return out
}
var UNITS = [
{ unit: 'North America', seed: 3 },
{ unit: 'Europe', seed: 41 },
{ unit: 'APAC', seed: 89 },
]
var metricSeries = []
UNITS.forEach(function (u, i) {
metricSeries.push({
name: 'value',
metric: 'Revenue',
unit: u.unit,
data: monthly(u.seed, 420 - i * 90, 14 - i * 3, 60),
})
metricSeries.push({
name: 'value',
metric: 'Margin',
unit: u.unit,
// Europe's margin erodes: visible only because the row shares a scale.
data: monthly(
u.seed + 7,
24 + i * 2,
u.unit === 'Europe' ? -0.9 : 0.1,
2.4,
),
})
metricSeries.push({
name: 'value',
metric: 'Headcount',
unit: u.unit,
data: monthly(u.seed + 13, 120 - i * 30, 2, 8),
})
})
var options = {
series: metricSeries,
chart: {
id: 'metricsTrellis',
type: 'line',
height: 560,
animations: {
enabled: false,
},
},
trellis: {
row: 'metric',
column: 'unit',
gap: 12,
scales: {
y: 'independent-row',
},
panel: function (key) {
if (key.indexOf('Revenue') === 0) {
return {
yaxis: {
labels: {
formatter: function (val) {
return '$' + Math.round(val) + 'k'
},
},
},
}
}
if (key.indexOf('Margin') === 0) {
return {
yaxis: {
labels: {
formatter: function (val) {
return Math.round(val) + '%'
},
},
},
}
}
return {
yaxis: {
labels: {
formatter: function (val) {
return String(Math.round(val))
},
},
},
}
},
},
colors: ['#0D9488'],
stroke: {
width: 2.5,
curve: 'straight',
},
xaxis: {
type: 'datetime',
},
dataLabels: {
enabled: false,
},
tooltip: {
x: {
format: 'MMM yyyy',
},
},
}
var chart = new ApexCharts(document.querySelector('#chart'), options)
chart.render()