I have been asked to create a bar graph similar to the above and I want to know if it is possible within chart.js?? I have had a look at a number of sites (such as Overlapping Bar Chart using Chart.js and https://github.com/chartjs/Chart.js/issues/5224) but the idea there is to have two graphs behind each other directly - I need to be able to set the position of the blocks (i.e. almost go something like margin-left:-5px
as I would in CSS) - or at least have some overlap (or about 40% overlap). If not I might have to build it in CSS but it would be great to use Chart JS.
Asked
Active
Viewed 1,167 times
0

Antony
- 3,875
- 30
- 32
-
I'm confused about the title of your post and the image you added to it. The title mentions a horizontal bar chart but the image shows a vertical bar chart. Can you please clarify? – uminder Sep 21 '20 at 15:18
-
But the bars are overlapping horizontally - yes it is a vertical graph though – Antony Sep 21 '20 at 15:23
-
Sorry, my bad. This makes it clear. – uminder Sep 21 '20 at 15:24
1 Answers
1
The Plugin Core API offers a range of hooks that may be used for performing custom code. You can use the afterUpdate
hook to shift the bars of individual datasets by the desired number of pixels as follows:
afterUpdate: function(chart) {
let datasets = chart.config.data.datasets;
for (let iDs = 1; iDs < datasets.length; iDs++) {
let dataset = datasets[iDs];
for (var i = 0; i < dataset._meta[0].data.length; i++) {
let model = dataset._meta[0].data[i]._model;
model.x += iDs * offset;
model.controlPointNextX += iDs * offset;
model.controlPointPreviousX += iDs * offset;
}
}
}
Please take a look at below runnable code snippet and see how it works.
const offset = 12;
new Chart('myChart', {
type: 'bar',
plugins: [{
afterUpdate: function(chart) {
let datasets = chart.config.data.datasets;
for (let iDs = 1; iDs < datasets.length; iDs++) {
let dataset = datasets[iDs];
for (var i = 0; i < dataset._meta[0].data.length; i++) {
let model = dataset._meta[0].data[i]._model;
model.x += iDs * offset;
model.controlPointNextX += iDs * offset;
model.controlPointPreviousX += iDs * offset;
}
}
}
}],
data: {
labels: ["A"],
datasets: [{
label: 'X',
backgroundColor: 'orange',
borderWidth: 1,
data: [5],
xAxisID: "bar-x-axis1",
barThickness: 30,
},
{
label: 'Y',
backgroundColor: 'red',
data: [10],
xAxisID: "bar-x-axis2",
barThickness: 30,
},
{
label: 'Z',
backgroundColor: 'lightblue',
data: [15],
xAxisID: "bar-x-axis3",
barThickness: 30,
}
]
},
options: {
legend: {
display: false
},
scales: {
xAxes: [{
id: "bar-x-axis3",
display: false
},
{
id: "bar-x-axis2",
offset: true,
display: false
},
{
id: "bar-x-axis1",
offset: true,
ticks: {
display: false
}
}
],
yAxes: [{
id: "bar-y-axis1",
ticks: {
beginAtZero: true,
stepSize: 5
}
}]
}
}
});
canvas {
max-width: 120px;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/Chart.js/2.9.3/Chart.min.js"></script>
<canvas id="myChart" height="150"></canvas>
UPDATE
Please also check this answer that provides a slightly improved solution.

uminder
- 23,831
- 5
- 37
- 72
-
Thank you for this - great answer! It works as expected however I have 2 graphs on the same page and I get an error `Cannot read property 'data' of undefined`. I know both graphs work independently but when put together it seems to error? – Antony Sep 22 '20 at 10:22
-
@Anthony: Please post a new question for this new issue, possibly with a code sample that reproduces the described error. This will make it much easier to come up with a solutions to this problem. – uminder Sep 22 '20 at 10:24
-
I have created the following js fiddle. I'm not sure it requires a new question though?? https://jsfiddle.net/ycpj7g8w/ – Antony Sep 22 '20 at 13:11