1👍
It is possible with a custom html legend, implementation is not perfect but I think its enough for you to finetune it so it will work execlty as you want
Example:
const getOrCreateLegendList = (chart, id) => {
const legendContainer = document.getElementById(id);
let listContainer = legendContainer.querySelector('ul');
if (!listContainer) {
listContainer = document.createElement('ul');
listContainer.style.display = 'flex';
listContainer.style.flexDirection = 'row';
listContainer.style.margin = 0;
listContainer.style.padding = 0;
legendContainer.appendChild(listContainer);
}
return listContainer;
};
const htmlLegendPlugin = {
id: 'htmlLegend',
afterUpdate(chart, args, options) {
const ul = getOrCreateLegendList(chart, options.containerID);
// Remove old legend items
while (ul.firstChild) {
ul.firstChild.remove();
}
// Reuse the built-in legendItems generator
const items = chart.options.plugins.legend.labels.generateLabels(chart);
items.forEach((item, i) => {
const li = document.createElement('li');
li.style.alignItems = 'center';
li.style.cursor = 'pointer';
li.style.display = 'flex';
li.style.flexDirection = 'row';
li.style.marginLeft = '10px';
li.onclick = () => {
const {
type
} = chart.config;
if (type === 'pie' || type === 'doughnut') {
// Pie and doughnut charts only have a single dataset and visibility is per item
chart.toggleDataVisibility(item.index);
} else {
chart.setDatasetVisibility(item.datasetIndex, !chart.isDatasetVisible(item.datasetIndex));
}
chart.update();
};
const datasets = chart.data.datasets;
// Color box
const boxSpan = document.createElement('span');
boxSpan.style.background = datasets[item.datasetIndex].backgroundColor[i];
boxSpan.style.borderColor = item.strokeStyle;
boxSpan.style.borderWidth = item.lineWidth + 'px';
boxSpan.style.display = 'inline-block';
boxSpan.style.height = '20px';
boxSpan.style.marginRight = '10px';
boxSpan.style.width = '20px';
const boxSpan2 = document.createElement('span');
boxSpan2.style.background = datasets[item.datasetIndex].backgroundColor[i + 1] || datasets[item.datasetIndex].backgroundColor[i - 1];
boxSpan2.style.borderColor = item.strokeStyle;
boxSpan2.style.borderWidth = item.lineWidth + 'px';
boxSpan2.style.borderColor = item.strokeStyle;
boxSpan2.style.borderWidth = item.lineWidth + 'px';
boxSpan2.style.display = 'inline-block';
boxSpan2.style.height = '20px';
boxSpan2.style.marginRight = '10px';
boxSpan2.style.width = '20px';
// Text
const textContainer = document.createElement('p');
textContainer.style.color = item.fontColor;
textContainer.style.margin = 0;
textContainer.style.padding = 0;
textContainer.style.textDecoration = item.hidden ? 'line-through' : '';
const text = document.createTextNode(item.text);
textContainer.appendChild(text);
li.appendChild(boxSpan);
li.appendChild(boxSpan2);
li.appendChild(textContainer);
ul.appendChild(li);
});
}
};
var options = {
type: 'bar',
data: {
labels: ["Red", "Blue"],
datasets: [{
label: '# of Votes',
data: [12, 19],
borderWidth: 1,
backgroundColor: ['rgb(224, 178, 40)', 'rgb(78, 235, 255)']
},
{
label: '# of Points',
data: [7, 11],
borderWidth: 1,
backgroundColor: ['rgb(204, 158, 20)', 'rgb(58, 215, 240)']
}
]
},
options: {
responsive: true,
scales: {
x: {
stacked: true,
grid: {
display: false
}
},
y: {
stacked: true,
grid: {
display: false
},
title: {
display: true,
text: 'Use, %'
}
}
},
plugins: {
htmlLegend: {
// ID of the container to put the legend in
containerID: 'chartjs-legend',
},
legend: {
display: false,
}
}
},
plugins: [htmlLegendPlugin],
}
var ctx = document.getElementById('chartJSContainer').getContext('2d');
new Chart(ctx, options);
<body>
<div id="chartjs-legend">
</div>
<canvas id="chartJSContainer" width="600" height="400"></canvas>
<script src="https://cdnjs.cloudflare.com/ajax/libs/Chart.js/3.3.2/chart.js"></script>
</body>
Source:stackexchange.com