Accepted answer

As I commented above, my preferred solution is to use ChartJS for these kinds of projects. I went ahead and took a quick stab at recreating your example chart with a (relatively) simple data transform to map your incoming data into a format that ChartJS can read.

The codepen for that is here

I would look at the code performing the data mapping/preprocessing for ChartJS below, as that is the most complicated bit of JavaScript involved in this process. The rest of the JS/HTML is just pulled from ChartJS documentation and the Stacked Chart sample here.

data.forEach((val) => {
  // Add the label if it doesn't exist already
  if(!barChartData.labels.includes(val.year)) {

  // Search for the correct dataset
  let valsDataset;
  let datasetName = `Dataset ${val.color}`;
  barChartData.datasets.forEach((dataset) => {
    if(dataset.label === datasetName) valsDataset = dataset;

  // Add the dataset if it doesn't exist already
  if(valsDataset === undefined) {
    valsDataset = {
      label: datasetName,
      backgroundColor: val.color,
      data: []

  // Find the correct index of the data array for this value, by looking up the year
  let valIndex = barChartData.labels.indexOf(val.year);
  // Set the correct data attribute according to val.value[valIndex] = val.value;

Fun project to work on this afternoon ;)

Related Query