1👍
Unfortunately it seems that Chart.js 2.8.0 supports reverse boolean parameter only for ticks object of yAxes.
This means, that without hacking or monkey patching it cannot be done within Chart.js API.
Also this dirty solution I came up with seems to be over-engineered, because simply changing dataset.data array item by referring to it by its index does not trigger Chart.js animations properly, therefore one needs to use splice.
Explanation:
Actually the idea is pretty simple:
In order to show bars from right to left for a priori known number of them
One needs to first create an array of length equal to number of bars and fill it with nulls.
In other words an array containing as many nulls as there are bars to be displayed.
Then each new value has to be inserted (using splice) from the right (end of the array) at first index under which array item is null or just simply at correct index, counting down from the array.length – 1 to 0.
“Visualisation”:
let value = 1;
const graphData = Array(3).fill(null);
console.log(graphData)
for(let i = graphData.length - 1; i >= 0; --i){
graphData.splice(i, 1, value++);
console.log(graphData)
}
Example:
class GraphController {
size = 0;
data = [];
labels = [];
graphData = [];
ctx = null;
chart = null;
constructor(size, data, labels, canvasId) {
this.size = size;
this.data = data;
this.labels = labels;
this.ctx = document.getElementById(canvasId).getContext('2d');
this.graphData = Array(size).fill(null);
}
fetchAndDraw(index = 1) {
const item = this.data[index - 1];
if (item.TotalReward) {
this.graphData[this.size - index] = item.TotalReward;
}
if (index > 1 && index < this.size) {
this.chart.data.datasets[0].data.splice(this.size - index, 1, item.TotalReward);
this.chart.update();
} else {
if (this.chart) {
this.chart.destroy();
}
this.chart = new Chart(this.ctx, {
type: 'bar',
data: {
labels: this.labels,
datasets: [{
data: [...this.graphData],
backgroundColor: '#fff',
hoverBackgroundColor: '#d5d5d5',
borderWidth: 0
}]
},
options: {
responsive: true,
maintainAspectRatio: false,
legend: {
display: false,
},
title: {
display: false,
},
tooltips: {
enabled: false,
},
scales: {
xAxes: [{
barPercentage: 1.0,
categoryPercentage: 0.55,
gridLines: {
display: false,
color: '#fff',
drawBorder: false,
zeroLineColor: '#fff'
},
ticks: {
fontFamily: '"Avenir Next", "Helvetica Neue", Arial, "Noto Sans", sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol", "Noto Color Emoji"',
fontSize: 16,
fontColor: '#fff',
padding: 15,
}
}],
yAxes: [{
categoryPercentage: 0.8,
barPercentage: 0.8,
gridLines: {
display: false,
color: '#fff',
drawBorder: false,
zeroLineColor: '#fff'
},
ticks: {
min: 0,
stepSize: 10,
fontFamily: '"Avenir Next", "Helvetica Neue", Arial, "Noto Sans", sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol", "Noto Color Emoji"',
fontSize: 16,
fontColor: '#fff',
padding: 10,
callback: function (value) {
return '$' + value;
}
}
}],
},
},
});
}
index++;
if (index <= this.size) {
setTimeout(() => {
this.fetchAndDraw(index);
}, 1000);
}
}
}
const data = [
{ "Month": "April ‘18", "TotalReward": 10.37 },
{ "Month": "May ‘18", "TotalReward": 18.11 },
{ "Month": "June ‘18", "TotalReward": 25.49 },
{ "Month": "January", "TotalReward": 35.55 },
{ "Month": "February", "TotalReward": 50.25 },
{ "Month": "March", "TotalReward": 59.15 },
]
const rewardLabels = ["April ‘18", "May ‘18", "June ‘18", "January", "February", "March"].reverse();
const graph = new GraphController(6, data, rewardLabels, 'rewardChart');
graph.fetchAndDraw();
.chart-wrap {
background: #333;
padding: 20px 10px;
}
<link href="https://cdnjs.cloudflare.com/ajax/libs/Chart.js/2.8.0/Chart.min.css" rel="stylesheet"/>
<script src="https://cdnjs.cloudflare.com/ajax/libs/Chart.js/2.8.0/Chart.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div class="chart-wrap">
<canvas id="rewardChart" width="600" height="165"></canvas>
</div>