A stacked or progress-style bar chart can show two related values in one bar. In this example, each class has a total number of students and a passed count. The outlined bar represents the total; the filled bar represents the passed count.
| Class | Total | Passed |
|---|---|---|
| Class-5 | 140 | 100 |
| Class-4 | 150 | 130 |
| Class-3 | 170 | 100 |
| Class-2 | 110 | 60 |
| Class-1 | 170 | 85 |
const data = [
['Class-5', 140, 100],
['Class-4', 150, 130]
];
const maxValue = Math.max(...data.map(row => row[1]));
const scale = plotHeight / maxValue;
const totalHeight = total * scale;
const passedHeight = passed * scale;
Scaling makes the chart independent of the raw value units. The original tutorial used pixel heights directly; that works only when data values conveniently fit the Canvas.
ctx.strokeRect(x, baseline - totalHeight, barWidth, totalHeight);
ctx.fillRect(x, baseline - passedHeight, barWidth, passedHeight);
See the basic bar chart and fillRect() for the underlying rectangle logic.
Keep the source values in a table or text summary so the chart is not the only representation of the data.
It is a nested/progress-style comparison: the passed value is drawn inside the total. A conventional stacked chart would place categories end-to-end.
Scaling maps arbitrary data values to available Canvas pixels.
Yes. Track the cumulative height of each segment.
Yes. Swap the value mapping from height to width.
No. Important values should also be available in semantic HTML.
Basic bar chart | Line graph | Canvas clock | Canvas reference
Author & Instructor at plus2net
I write and maintain practical tutorials on Python, PHP, SQL, JavaScript, HTML, jQuery, and web development at plus2net. The tutorials focus on clear explanations, working examples, and code that readers can test and adapt while learning.