Reputation: 97
I am trying to create a barchart with several different datasets but I'm struggling with getting labels below each bar. This is what I currently have.
I want to have labels below the bars as well, not just in the legend. Below is my data var.
{
"labels": [
""
],
"datasets": [
{
"label": "testname1",
"borderColor": "rgba(254, 112, 150, 1)",
"backgroundColor": "rgba(254, 112, 150, 1)",
"borderWidth": 1,
"categoryPercentage": 1,
"data": [
58
]
},
{
"label": "testname2",
"borderColor": "rgba(54, 215, 232, 1)",
"backgroundColor": "rgba(54, 215, 232, 1)",
"borderWidth": 1,
"categoryPercentage": 1,
"data": [
60
]
},
{
"label": "testname3",
"borderColor": "rgba(6, 185, 157, 1)",
"backgroundColor": "rgba(6, 185, 157, 1)",
"borderWidth": 1,
"categoryPercentage": 1,
"data": [
21
]
},
{
"label": "testname4",
"borderColor": "rgba(242, 197, 124, 1)",
"backgroundColor": "rgba(242, 197, 124, 1)",
"borderWidth": 1,
"categoryPercentage": 1,
"data": [
35
]
},
{
"label": "testname5",
"borderColor": "rgba(54,70,82, 1)",
"backgroundColor": "rgba(54,70,82, 1)",
"borderWidth": 1,
"categoryPercentage": 1,
"data": [
32
]
},
{
"label": "testname6",
"borderColor": "rgba(68, 94, 147, 1)",
"backgroundColor": "rgba(68, 94, 147, 1)",
"borderWidth": 1,
"categoryPercentage": 1,
"data": [
75
]
},
{
"label": "testname7",
"borderColor": "rgba(143, 57, 133, 1)",
"backgroundColor": "rgba(143, 57, 133, 1)",
"borderWidth": 1,
"categoryPercentage": 1,
"data": [
5
]
},
{
"label": "testname8",
"borderColor": "rgba(255, 209, 102, 1)",
"backgroundColor": "rgba(255, 209, 102, 1)",
"borderWidth": 1,
"categoryPercentage": 1,
"data": [
0
]
},
{
"label": "testname9",
"borderColor": "rgba(67, 129, 193, 1)",
"backgroundColor": "rgba(67, 129, 193, 1)",
"borderWidth": 1,
"categoryPercentage": 1,
"data": [
42
]
},
{
"label": "testname10",
"borderColor": "rgba(135, 61, 72, 1)",
"backgroundColor": "rgba(135, 61, 72, 1)",
"borderWidth": 1,
"categoryPercentage": 1,
"data": [
76
]
},
{
"label": "testname11",
"borderColor": "rgba(42, 71, 71, 1)",
"backgroundColor": "rgba(42, 71, 71, 1)",
"borderWidth": 1,
"categoryPercentage": 1,
"data": [
75
]
},
{
"label": "testname12",
"borderColor": "rgba(237, 191, 133, 1)",
"backgroundColor": "rgba(237, 191, 133, 1)",
"borderWidth": 1,
"categoryPercentage": 1,
"data": [
34
]
},
{
"label": "testname13",
"borderColor": "rgba(187, 40, 55, 1)",
"backgroundColor": "rgba(187, 40, 55, 1)",
"borderWidth": 1,
"categoryPercentage": 1,
"data": [
59
]
},
{
"label": "testname14",
"borderColor": "rgba(115, 92, 221, 1)",
"backgroundColor": "rgba(115, 92, 221, 1)",
"borderWidth": 1,
"categoryPercentage": 1,
"data": [
98
]
},
{
"label": "testname15",
"borderColor": "rgba(144, 0, 179, 1)",
"backgroundColor": "rgba(144, 0, 179, 1)",
"borderWidth": 1,
"categoryPercentage": 1,
"data": [
64
]
}
]
}
This is my options
{
"scales": {
"y": {
"ticks": {
"display": true
}
},
"x": {
"display": false
}
},
"plugins": {
"legend": {
"display": {
"displayLegend": true
},
"position": "top"
},
"tooltip": {
"callbacks": {}
},
"elements": {
"point": {
"radius": 0
}
}
}
}
I can manage to add the labels below the columns if I make it all 1 dataset but then all columns are the same color and you cant toggle them. I also tried this link Chart.js manipulate each bar in chart with different labels. But this is for version two of chartjs and doesnt work in the current version anymore. The paths in the beforelayout plugin keep returning cant set on undefined and when I did find xAxes in the chart object it was undefined.
Does anyone know how to get labels under my barchart columns without making it all one dataset?
Upvotes: 1
Views: 60
Reputation: 8495
You can add a supplemental x axis, and set the labels of that axis to the labels of the visible datasets in the afterTickToLabelConversion callback of that axis.
The configuration of that axis may look like this:
x_dataset_labels: {
type: "linear",
min: 0,
max: 1,
afterTickToLabelConversion(scale){
const chart = scale.chart;
const visible = Array.from({length: chart.data.datasets.length},
(_, i)=>!chart.getDatasetMeta(i).hidden ? i : false).filter(vis => vis!==false),
nVisible = visible.length;
scale.ticks = Array.from({length: nVisible}, (_, i) => ({
value: (i+0.5)/nVisible, label: chart.data.datasets[visible[i]].label || ''
}));
},
offset: false
}
A snippet with the data and options in the question and this axis added:
const data = {
"labels": [
""
],
"datasets": [
{
"label": "testname1",
"borderColor": "rgba(254, 112, 150, 1)",
"backgroundColor": "rgba(254, 112, 150, 1)",
"borderWidth": 1,
"categoryPercentage": 1,
"data": [
58
]
},
{
"label": "testname2",
"borderColor": "rgba(54, 215, 232, 1)",
"backgroundColor": "rgba(54, 215, 232, 1)",
"borderWidth": 1,
"categoryPercentage": 1,
"data": [
60
]
},
{
"label": "testname3",
"borderColor": "rgba(6, 185, 157, 1)",
"backgroundColor": "rgba(6, 185, 157, 1)",
"borderWidth": 1,
"categoryPercentage": 1,
"data": [
21
]
},
{
"label": "testname4",
"borderColor": "rgba(242, 197, 124, 1)",
"backgroundColor": "rgba(242, 197, 124, 1)",
"borderWidth": 1,
"categoryPercentage": 1,
"data": [
35
]
},
{
"label": "testname5",
"borderColor": "rgba(54,70,82, 1)",
"backgroundColor": "rgba(54,70,82, 1)",
"borderWidth": 1,
"categoryPercentage": 1,
"data": [
32
]
},
{
"label": "testname6",
"borderColor": "rgba(68, 94, 147, 1)",
"backgroundColor": "rgba(68, 94, 147, 1)",
"borderWidth": 1,
"categoryPercentage": 1,
"data": [
75
]
},
{
"label": "testname7",
"borderColor": "rgba(143, 57, 133, 1)",
"backgroundColor": "rgba(143, 57, 133, 1)",
"borderWidth": 1,
"categoryPercentage": 1,
"data": [
5
]
},
{
"label": "testname8",
"borderColor": "rgba(255, 209, 102, 1)",
"backgroundColor": "rgba(255, 209, 102, 1)",
"borderWidth": 1,
"categoryPercentage": 1,
"data": [
0
]
},
{
"label": "testname9",
"borderColor": "rgba(67, 129, 193, 1)",
"backgroundColor": "rgba(67, 129, 193, 1)",
"borderWidth": 1,
"categoryPercentage": 1,
"data": [
42
]
},
{
"label": "testname10",
"borderColor": "rgba(135, 61, 72, 1)",
"backgroundColor": "rgba(135, 61, 72, 1)",
"borderWidth": 1,
"categoryPercentage": 1,
"data": [
76
]
},
{
"label": "testname11",
"borderColor": "rgba(42, 71, 71, 1)",
"backgroundColor": "rgba(42, 71, 71, 1)",
"borderWidth": 1,
"categoryPercentage": 1,
"data": [
75
]
},
{
"label": "testname12",
"borderColor": "rgba(237, 191, 133, 1)",
"backgroundColor": "rgba(237, 191, 133, 1)",
"borderWidth": 1,
"categoryPercentage": 1,
"data": [
34
]
},
{
"label": "testname13",
"borderColor": "rgba(187, 40, 55, 1)",
"backgroundColor": "rgba(187, 40, 55, 1)",
"borderWidth": 1,
"categoryPercentage": 1,
"data": [
59
]
},
{
"label": "testname14",
"borderColor": "rgba(115, 92, 221, 1)",
"backgroundColor": "rgba(115, 92, 221, 1)",
"borderWidth": 1,
"categoryPercentage": 1,
"data": [
98
]
},
{
"label": "testname15",
"borderColor": "rgba(144, 0, 179, 1)",
"backgroundColor": "rgba(144, 0, 179, 1)",
"borderWidth": 1,
"categoryPercentage": 1,
"data": [
64
]
}
]
};
const options = {
"scales": {
"y": {
"ticks": {
"display": true
}
},
"x": {
"display": false
},
x_dataset_labels: {
type: "linear",
min: 0,
max: 1,
afterTickToLabelConversion(scale){
const chart = scale.chart;
const visible = Array.from({length: chart.data.datasets.length},
(_, i)=>!chart.getDatasetMeta(i).hidden ? i : false).filter(vis => vis!==false),
nVisible = visible.length;
scale.ticks = Array.from({length: nVisible}, (_, i) => ({
value: (i+0.5)/nVisible, label: chart.data.datasets[visible[i]].label || ''
}));
},
offset: false
}
},
"plugins": {
"legend": {
"display": {
"displayLegend": true
},
"position": "top"
},
"tooltip": {
"callbacks": {}
},
"elements": {
"point": {
"radius": 0
}
}
}
};
new Chart("myChart", {type: "bar", data, options});
<div style="height:70vh">
<canvas id="myChart"></canvas>
</div>
<script src="https://cdn.jsdelivr.net/npm/chart.js"></script>
The same, with the addition of axis implemented as in a plugin, that also has some options for grid and tick marks:
const data = {
"labels": [
""
],
"datasets": [
{
"label": "testname1",
"borderColor": "rgba(254, 112, 150, 1)",
"backgroundColor": "rgba(254, 112, 150, 1)",
"borderWidth": 1,
"categoryPercentage": 1,
"data": [
58
]
},
{
"label": "testname2",
"borderColor": "rgba(54, 215, 232, 1)",
"backgroundColor": "rgba(54, 215, 232, 1)",
"borderWidth": 1,
"categoryPercentage": 1,
"data": [
60
]
},
{
"label": "testname3",
"borderColor": "rgba(6, 185, 157, 1)",
"backgroundColor": "rgba(6, 185, 157, 1)",
"borderWidth": 1,
"categoryPercentage": 1,
"data": [
21
]
},
{
"label": "testname4",
"borderColor": "rgba(242, 197, 124, 1)",
"backgroundColor": "rgba(242, 197, 124, 1)",
"borderWidth": 1,
"categoryPercentage": 1,
"data": [
35
]
},
{
"label": "testname5",
"borderColor": "rgba(54,70,82, 1)",
"backgroundColor": "rgba(54,70,82, 1)",
"borderWidth": 1,
"categoryPercentage": 1,
"data": [
32
]
},
{
"label": "testname6",
"borderColor": "rgba(68, 94, 147, 1)",
"backgroundColor": "rgba(68, 94, 147, 1)",
"borderWidth": 1,
"categoryPercentage": 1,
"data": [
75
]
},
{
"label": "testname7",
"borderColor": "rgba(143, 57, 133, 1)",
"backgroundColor": "rgba(143, 57, 133, 1)",
"borderWidth": 1,
"categoryPercentage": 1,
"data": [
5
]
},
{
"label": "testname8",
"borderColor": "rgba(255, 209, 102, 1)",
"backgroundColor": "rgba(255, 209, 102, 1)",
"borderWidth": 1,
"categoryPercentage": 1,
"data": [
0
]
},
{
"label": "testname9",
"borderColor": "rgba(67, 129, 193, 1)",
"backgroundColor": "rgba(67, 129, 193, 1)",
"borderWidth": 1,
"categoryPercentage": 1,
"data": [
42
]
},
{
"label": "testname10",
"borderColor": "rgba(135, 61, 72, 1)",
"backgroundColor": "rgba(135, 61, 72, 1)",
"borderWidth": 1,
"categoryPercentage": 1,
"data": [
76
]
},
{
"label": "testname11",
"borderColor": "rgba(42, 71, 71, 1)",
"backgroundColor": "rgba(42, 71, 71, 1)",
"borderWidth": 1,
"categoryPercentage": 1,
"data": [
75
]
},
{
"label": "testname12",
"borderColor": "rgba(237, 191, 133, 1)",
"backgroundColor": "rgba(237, 191, 133, 1)",
"borderWidth": 1,
"categoryPercentage": 1,
"data": [
34
]
},
{
"label": "testname13",
"borderColor": "rgba(187, 40, 55, 1)",
"backgroundColor": "rgba(187, 40, 55, 1)",
"borderWidth": 1,
"categoryPercentage": 1,
"data": [
59
]
},
{
"label": "testname14",
"borderColor": "rgba(115, 92, 221, 1)",
"backgroundColor": "rgba(115, 92, 221, 1)",
"borderWidth": 1,
"categoryPercentage": 1,
"data": [
98
]
},
{
"label": "testname15",
"borderColor": "rgba(144, 0, 179, 1)",
"backgroundColor": "rgba(144, 0, 179, 1)",
"borderWidth": 1,
"categoryPercentage": 1,
"data": [
64
]
}
]
};
const options = {
"scales": {
"y": {
"ticks": {
"display": true
}
},
"x": {
"display": false
}
},
"plugins": {
"legend": {
"display": {
"displayLegend": true
},
"position": "top"
},
"tooltip": {
"callbacks": {}
},
"elements": {
"point": {
"radius": 0
}
},
one_bar_datasets_x_labels: {
tickLength: 8,
color: 'rgba(0, 0, 0, 0.3)',
gridVisible: true,
gridLineDash: [5, 5]
}
}
};
const pluginOneBarDatasetsXLabels = {
id: 'one_bar_datasets_x_labels',
beforeInit(chart, _, options){
chart.options.scales.x_dataset_labels = {}
chart.options.scales.x_dataset_labels.type = 'linear';
chart.options.scales.x_dataset_labels.min = 0;
chart.options.scales.x_dataset_labels.max = 1;
chart.options.scales.x_dataset_labels.offset = false;
chart.options.scales.x_dataset_labels.grid = {};
chart.options.scales.x_dataset_labels.grid.display = !!options.gridVisible;
if(options.tickLength || options.color){
chart.options.scales.x_dataset_labels.grid.tickLength = options.tickLength || 0;
chart.options.scales.x_dataset_labels.grid.color = options.color || 'rgba(0,0,0,0.1)';
}
if(options.gridLineDash){
chart.options.scales.x_dataset_labels.border = {};
chart.options.scales.x_dataset_labels.border.dash = options.gridLineDash;
}
chart.options.scales.x_dataset_labels.afterTickToLabelConversion = function(scale){
const visible = Array.from({length: scale.chart.data.datasets.length},
(_, i)=>!scale.chart.getDatasetMeta(i).hidden ? i : false).filter(vis => vis!==false),
nVisible = visible.length;
scale.ticks = Array.from({length: nVisible}, (_, i) => ({
value: (i+0.5)/nVisible, label: scale.chart.data.datasets[visible[i]].label || ''
}));
}
}
}
new Chart("myChart", {type: "bar", data, options, plugins: [pluginOneBarDatasetsXLabels]});
<div style="height:70vh">
<canvas id="myChart"></canvas>
</div>
<script src="https://cdn.jsdelivr.net/npm/chart.js"></script>
Upvotes: 1