0👍
✅
Your problem can be solved with Chart.js but the labels
and the single dataset
need to be generated.
Further you need to define your own legend
by defining a plugins.legend.labels.generateLabels
together with with a plugins.legend.labels.onClick
function.
For further information, consult the Legend page from the Chart.js. documentation.
Please take a look at your amended and runnable code below and see how it works.
const baseData = {
labels: ['2000','2010','2020'],
datasets: [
{ label: 'Frogs', data: [30.2, 20.8, 36.2], bgColor: 'red', hidden: false },
{ label: 'Monkeys', data: [16.3, 13.0, 22.3], bgColor: 'blue', hidden: false },
{ label: 'Squirrels', data: [5.8,3.1, 14.9], bgColor: 'cyan', hidden: false },
{ label: 'Bats', data: [0.1, 3.6, 2.6], bgColor: 'aquamarine', hidden: false }
]
};
const iLastDs = baseData.datasets.length - 1;
const data = {
labels: baseData.datasets
.map(() => baseData.labels)
.map((labels, i) => i < iLastDs ? [...labels, null] : labels)
.flatMap(v => v),
datasets: [{
data: baseData.datasets
.map(ds => ds.data)
.map((data, i) => i < iLastDs ? [...data, null] : data)
.flatMap(v => v),
backgroundColor: baseData.datasets
.map(ds => ds.data.map(v => ds.bgColor))
.map((bgColors, i) => i < iLastDs ? [...bgColors, null] : bgColors)
.flatMap(v => v),
categoryPercentage: 1,
barPercentage: 0.9
}]
};
const options = {
maintainAspectRatio: true,
responsive: true,
interaction: {
intersect: true,
mode: 'index',
},
plugins: {
legend: {
position: 'bottom',
labels: {
generateLabels: chart => baseData.datasets.map((ds, i) => ({
datasetIndex: i,
text: ds.label,
fillStyle: ds.bgColor,
strokeStyle: 'lightgray',
hidden: baseData.datasets[i].hidden
}))
},
onClick: (event, legendItem, legend) => {
baseData.datasets[legendItem.datasetIndex].hidden = !baseData.datasets[legendItem.datasetIndex].hidden;
const iFirstValue = legendItem.datasetIndex + legendItem.datasetIndex * baseData.labels.length;
for (let i = iFirstValue; i < iFirstValue + baseData.labels.length; i++) {
legend.chart.toggleDataVisibility(i);
}
legend.chart.update();
}
},
tooltip: {
callbacks: {
title: ctx => {
const dsIndex = Math.floor(ctx[0].dataIndex / baseData.datasets.length);
return baseData.datasets[dsIndex].label + ' / ' + ctx[0].label;
}
}
}
},
scales: {
x: {
grid: {
display: false
}
},
y: {
title: {
display: true,
text: 'Horsepower',
}
}
}
};
new Chart('mychart', {
type: 'bar',
data,
options
});
span {
font-style: italic;
font-size: 12px;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/Chart.js/3.9.1/chart.min.js"></script>
<canvas id="mychart" height="100"></canvas>
<span>Source: Animals Index, June 2022</span>
Source:stackexchange.com