The default functionality of label item text having a strikethrough applied when clicking on it from within the legend is not working. I would like to fix this issue so the strikethrough is applied (or toggled off) when clicked and the corresponding data is hidden from or shown to the chart.
const outsourcedProductionNames = ["Development", "Content", "Design"];
const outsourcedProductionCounts = new Array(outsourcedProductionNames.length).fill(0);
// Function to truncate text and add ellipses
function truncateText(text, maxLength) {
if (text.length > maxLength) {
return text.substring(0, maxLength) + '...';
}
return text;
}
// Function to generate distinct colors
function generateDistinctColors(count) {
const colors = [];
for (let i = 0; i < count; i++) {
const hue = i * (360 / count);
colors.push(`hsl(${hue}, 100%, 75%)`);
}
return colors;
}
// Generate distinct colors for the chart
const colors = generateDistinctColors(outsourcedProductionNames.length);
const ctx = document.getElementById('allChartsOutsourcedProduction').getContext('2d');
new Chart(ctx, {
type: 'pie',
data: {
labels: outsourcedProductionNames,
datasets: [{
label: 'Outsourced Production',
data: outsourcedProductionCounts,
backgroundColor: colors,
borderColor: 'white',
borderWidth: 2
}]
},
options: {
aspectRatio: 1.5,
plugins: {
legend: {
labels: {
filter: (legendItem, data) => data.datasets[0].data[legendItem.index] != 0,
generateLabels: function(chart) {
return chart.data.labels.map((label, index) => {
return {
text: truncateText(label, 20),
fillStyle: chart.data.datasets[0].backgroundColor[index],
strokeStyle: undefined, // Remove the border color
lineWidth: 0, // Remove the border width
hidden: chart.getDatasetMeta(0).data[index].hidden,
index: index
};
});
}
}
},
tooltip: {
titleFont: {
family: "sans-serif",
weight: 900
},
callbacks: {
label: data => (' ' + data.parsed + ' Projects')
}
}
}
}
});
I have tried making a separate plugin for the strikethrough function. This worked to get the strike through, but it caused my tooltip styling, truncate function, and filter (having items not show in legend that have 0 results) to not work.
It took me a lot of debugging to realize that the problem in your code is just at value of the hidden
parameter.
The function generateLabels
is called not only at the initialization of the chart (as its name might suggest), but
also each time an item's visibility is toggled. However, after the click on a legend item, the
value of chart.getDatasetMeta(0).data[index].hidden
that you use is not changed, it will stay false
or undefined
that's why you should use !chart.getDataVisibility(index)
as it is done in the source code, which, by the looks of it you have already consulted.
In short, the only replacement required is
......
hidden: !chart.getDataVisibility(index),
......
Snippet, that also logs each time getDataVisibility
is called:
const outsourcedProductionNames = ["Development", "Content", "Design"];
const outsourcedProductionCounts = new Array(outsourcedProductionNames.length).fill(1);
// Function to truncate text and add ellipses
function truncateText(text, maxLength) {
if (text.length > maxLength) {
return text.substring(0, maxLength) + '...';
}
return text;
}
// Function to generate distinct colors
function generateDistinctColors(count) {
const colors = [];
for (let i = 0; i < count; i++) {
const hue = i * (360 / count);
colors.push(`hsl(${hue}, 100%, 75%)`);
}
return colors;
}
// Generate distinct colors for the chart
const colors = generateDistinctColors(outsourcedProductionNames.length);
let logEnabled = false;
const ctx = document.getElementById('allChartsOutsourcedProduction').getContext('2d');
new Chart(ctx, {
type: 'pie',
data: {
labels: outsourcedProductionNames,
datasets: [{
label: 'Outsourced Production',
data: outsourcedProductionCounts,
backgroundColor: colors,
borderColor: 'white',
borderWidth: 2
}]
},
options: {
aspectRatio: 1.5,
plugins: {
legend: {
labels: {
filter: (legendItem, data) => data.datasets[0].data[legendItem.index] != 0,
generateLabels: function(chart) {
if(logEnabled) console.log('generateLabels called');
return chart.data.labels.map((label, index) => {
return {
text: truncateText(label, 20),
fillStyle: chart.data.datasets[0].backgroundColor[index],
strokeStyle: undefined, // Remove the border color
lineWidth: 0, // Remove the border width
hidden: !chart.getDataVisibility(index),
index: index
};
});
}
}
},
tooltip: {
titleFont: {
family: "sans-serif",
weight: 900
},
callbacks: {
label: data => (' ' + data.parsed + ' Projects')
}
}
}
}
});
setTimeout(()=>{logEnabled = true;}, 1000); // log only after the chart is built and animation over
<div style="min-height: 60vh">
<canvas id="allChartsOutsourcedProduction">
</canvas>
</div>
<script src="https://cdn.jsdelivr.net/npm/chart.js"></script>