I'm working on my project and I need to show the labels of the bar chart exactly on the bars like this:
I can't get it to work...basically labels are never shown on the bars...they are shown above, below or not shown.
This is my current code:
import { Bar } from 'react-chartjs-2';
import {
Chart,
CategoryScale,
LinearScale,
BarElement,
Title,
Tooltip,
Legend,
} from 'chart.js';
import {
ChartName,
ChartSubtitle,
ChartWrapper,
} from './HorizontalChartStyles';
Chart.register(CategoryScale, LinearScale, BarElement, Title, Tooltip, Legend);
const HorizontalChart = () => {
const options = {
maintainAspectRatio: true,
indexAxis: 'y',
elements: {
bar: {
borderWidth: 0,
},
},
responsive: true,
plugins: {
legend: {
display: false,
},
title: {
display: false,
text: 'Attendance per lecture',
},
tooltip: {
enabled: false,
},
datalabels: {
anchor: 'end',
align: 'end',
color: 'black',
font: {
weight: 'bold',
},
formatter: (value) => `${value}%`,
labels: {
value: {
display: true,
},
},
},
},
scales: {
y: {
display: false,
},
x: {
ticks: {
display: true,
},
grid: {
display: false,
},
scaleLabel: {
display: true,
labelString: 'Percentage',
},
},
},
layout: {
padding: {
right: 20,
},
},
text: {
color: 'black',
anchor: 'end',
},
};
const labels = [
'1. Introduction:',
'2. HTML & CSS:',
'3. Version Control System:',
'4. Advanced CSS:',
'5. Intro to JS:',
'6. Advanced JS:',
'7. Intro to React:',
];
const getRandomNumber = (min, max) => {
return Math.floor(Math.random() * (max - min + 1) + min);
};
const generateRandomData = () => {
return labels.map(() => getRandomNumber(0, 100));
};
const getColor = (value) => {
if (value === 100) return '#CB7B2C';
if (value >= 90) {
const transparency = (value - 90) / 10;
return `rgba(203, 123, 44, ${transparency})`;
}
if (value >= 70) return '#CB7B2C';
return '#DCDEDF';
};
const data = {
labels: labels,
datasets: [
{
label: 'Dataset 1',
data: generateRandomData(),
backgroundColor: generateRandomData().map((value) => getColor(value)),
barPercentage: 1,
categoryPercentage: 1,
},
],
};
return (
<ChartWrapper>
<ChartName>Attendance per lecture (%)</ChartName>
<ChartSubtitle>Your attendance</ChartSubtitle>
<Bar data={data} options={options} style={{ flex: 1 }} />
</ChartWrapper>
);
};
export default HorizontalChart;
I tried modifying the options numerous times, nothing seemed to work. Currently my output looks like this:
const [options, setOptions] = useState({
responsive: true,
indexAxis: 'y',
plugins: {
legend: {
display: false,
},
title: {
display: false,
},
tooltip: {
callbacks: {
label: function (context) {
const label =
context.chart.data.labels[context.dataIndex]?.tooltip ?? '';
return label;
},
title: function (context) {
const title =
context[0].chart.data.labels[context[0].dataIndex]?.label ?? '';
return title;
},
},
},
datalabels: {
color: (context) =>
getTextColor(context.dataset.data[context.dataIndex]),
align: 'end',
anchor: 'center',
formatter: function (value, context) {
return `${
context.chart.data.labels[context.dataIndex]?.label
}: ${value}%`;
},
font: function () {
return {
size: 12,
};
},
},
},
hover: {
mode: null,
},
scales: {
x: {
grid: {
display: false,
},
},
y: {
grid: {
display: false,
},
ticks: {
display: false,
reverse: true,
},
},
},
layout: {
padding: {
left: window.innerWidth >= breakPoints.mobileLarge ? 24 : 0,
},
}, });