3👍
✅
Based on this answer, I created a runnable code snippet that illustrates how it could be done. I’m not using stacked bars because the use case is not clear to me and the image from the question rather looks like a bar with shadows.
const dataset = [40, 80, 50, 60, 70];
const offset = 8;
Chart.pluginService.register({
afterUpdate: function(chart) {
var dataset = chart.config.data.datasets[1];
for (var i = 0; i < dataset._meta[0].data.length; i++) {
var model = dataset._meta[0].data[i]._model;
model.x += offset;
model.controlPointNextX += offset;
model.controlPointPreviousX += offset;
}
}
});
var data = {
labels: ["A", "B", "C", "D", "E"],
datasets: [{
backgroundColor: [
'rgba(255, 99, 132)',
'rgba(255, 206, 86)',
'rgba(54, 162, 235)',
'rgba(75, 192, 192)',
'rgba(153, 102, 255)'
],
borderWidth: 1,
data: dataset,
xAxisID: "bar-x-axis1",
categoryPercentage: 0.5,
barPercentage: 0.5,
},
{
backgroundColor: 'rgba(0, 0, 0, 0.2)',
data: dataset.map(v => v + offset),
xAxisID: "bar-x-axis2",
categoryPercentage: 0.5,
barPercentage: 0.5
}
]
};
var options = {
legend: {
display: false
},
tooltips: {
enabled: false
},
scales: {
xAxes: [
{
id: "bar-x-axis2"
},
{
id: "bar-x-axis1",
offset: true,
ticks: {
display: false
}
}
],
yAxes: [{
id: "bar-y-axis1",
ticks: {
beginAtZero: true,
stepSize: 50
}
}]
}
};
var ctx = document.getElementById("myChart").getContext("2d");
var myBarChart = new Chart(ctx, {
type: 'bar',
data: data,
options: options
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/Chart.js/2.9.3/Chart.min.js"></script>
<canvas id="myChart" height="60"></canvas>
1👍
For Chart.js v3, you can use a different approach.
- In the
beforeDatasetsDraw
, you save the define the shadow properties on the canvas through CanvasRenderingContext2D. Make sure to first save the state of the rendering context by invokingctx.save()
. - In the
afterDatasetsDraw
hook, you need to restore the state of the rendering context by invokingctx.restore()
. - Convert the bars into floating bars through
data: data.map(v => [-20, v])
to makes sure, the shadows appear from the base of the bars. - Define a
tooltip.callbacks.label
function that provides the initial values in the tooltips.
Please take a look at below runnable code and see how it works.
const data = [40, 80, 50, 60, 70];
const offset = 10;
new Chart('myChart', {
type: 'bar',
plugins: [{
beforeDatasetsDraw: chart => {
const ctx = chart.ctx;
ctx.save();
ctx.shadowOffsetX = offset;
ctx.shadowOffsetY = -offset;
ctx.shadowBlur = 5;
ctx.shadowColor = 'rgb(220, 220, 220)';
},
afterDatasetsDraw: chart => chart.ctx.restore()
}],
data: {
labels: ["A", "B", "C", "D", "E"],
datasets: [{
label: 'My Data',
data: data.map(v => [-20, v]),
backgroundColor: [
'rgba(255, 99, 132)',
'rgba(255, 206, 86)',
'rgba(54, 162, 235)',
'rgba(75, 192, 192)',
'rgba(153, 102, 255)'
],
categoryPercentage: 0.8
}]
},
options: {
plugins: {
tooltip: {
callbacks: {
label: ctx => data[ctx.dataIndex]
}
}
},
scales: {
y: {
min: 0,
max: Math.max(...data) + offset
}
}
}
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/Chart.js/3.7.1/chart.min.js"></script>
<canvas id="myChart" height="100"></canvas>
Source:stackexchange.com