window.chartColors = {
red: '#ffb5c5',
orange: '#FFA500',
yellow: '#F0E68C',
green: '#aee0e0',
blue: '#87CEFA',
purple: '#EE82EE',
grey: '#C0C0C0'
};
$(document).ready(function() {
var data = [{
"tc": "1.25173997",
"trf": "0.00000024",
"nc": "1.00139199",
"formatted_date": "temmp1",
"from_date": "2019-02-01 00:00:00",
"to_date": "2019-02-08 23:59:59"
}, ];
var formatted_date = [];
var tcs = [];
var trps = [];
var ncs = [];
// var data = $.parseJSON(data);
$.each(data, function(index, item) {
formatted_date.push(item.formatted_date);
tcs.push(item.tc);
trps.push(item.trf);
ncs.push(item.nc);
});
refData = [{
label: 'C',
backgroundColor: window.chartColors.blue,
borderColor: window.chartColors.blue,
data: tcs,
fill: false,
/* cubicInterpolationMode: 'monotone' */
},
{
label: 'R P',
backgroundColor: window.chartColors.red,
borderColor: window.chartColors.red,
data: trps,
fill: false
},
{
label: 'N C',
backgroundColor: window.chartColors.green,
borderColor: window.chartColors.green,
data: ncs,
fill: false
},
];
var chartdata = {
labels: formatted_date,
datasets: refData
};
//console.log(chartdata);
var graphTarget = $("#myChart");
var Graph = new Chart(graphTarget, {
type: 'line',
data: chartdata,
options: {
responsive: true,
title: {
display: true,
text: 'R P'
},
scales: {
xAxes: [{
// stacked: true,
display: true,
scaleLabel: {
display: true,
labelString: 'Duration'
}
}],
yAxes: [{
// stacked: true,
display: true,
scaleLabel: {
display: true,
labelString: 'Amt'
},
ticks: {
min: 0, // it is for ignoring negative step.
}
}]
},
},
});
})
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/Chart.js/2.7.3/Chart.min.js"></script>
<div style="width:75%;">
<canvas id="myChart"></canvas>
</div>
As you can see for R P 0.00000024 is getting converted into 2.4e-7. But I want it show as is i.e. 0.00000024.
For other decimals numbers, it's perfectly fine, but for the above-mentioned decimal, it's converting into exponential. Is there any option to set? Is this possible?
With the help of this solution, I patched my problem. If anyone got better solution let me know.
Number.prototype.noExponents = function() {
var data = String(this).split(/[eE]/);
if (data.length == 1) return data[0];
var z = '',
sign = this < 0 ? '-' : '',
str = data[0].replace('.', ''),
mag = Number(data[1]) + 1;
if (mag < 0) {
z = sign + '0.';
while (mag++) z += '0';
return z + str.replace(/^\-/, '');
}
mag -= str.length;
while (mag--) z += '0';
return str + z;
}
window.chartColors = {
red: '#ffb5c5',
orange: '#FFA500',
yellow: '#F0E68C',
green: '#aee0e0',
blue: '#87CEFA',
purple: '#EE82EE',
grey: '#C0C0C0'
};
$(document).ready(function() {
var data = [{
"tc": "1.25173997",
"trf": "0.00000024",
"nc": "1.00139199",
"formatted_date": "temmp1",
"from_date": "2019-02-01 00:00:00",
"to_date": "2019-02-08 23:59:59"
}, ];
var formatted_date = [];
var tcs = [];
var trps = [];
var ncs = [];
// var data = $.parseJSON(data);
$.each(data, function(index, item) {
formatted_date.push(item.formatted_date);
tcs.push(item.tc);
trps.push(item.trf);
ncs.push(item.nc);
});
refData = [{
label: 'C',
backgroundColor: window.chartColors.blue,
borderColor: window.chartColors.blue,
data: tcs,
fill: false,
/* cubicInterpolationMode: 'monotone' */
},
{
label: 'R P',
backgroundColor: window.chartColors.red,
borderColor: window.chartColors.red,
data: trps,
fill: false
},
{
label: 'N C',
backgroundColor: window.chartColors.green,
borderColor: window.chartColors.green,
data: ncs,
fill: false
},
];
var chartdata = {
labels: formatted_date,
datasets: refData
};
//console.log(chartdata);
var graphTarget = $("#myChart");
var Graph = new Chart(graphTarget, {
type: 'line',
data: chartdata,
options: {
responsive: true,
title: {
display: true,
text: 'R P'
},
scales: {
xAxes: [{
// stacked: true,
display: true,
scaleLabel: {
display: true,
labelString: 'Duration'
}
}],
yAxes: [{
// stacked: true,
display: true,
scaleLabel: {
display: true,
labelString: 'Amt'
},
ticks: {
min: 0, // it is for ignoring negative step.
}
}]
},
tooltips: {
callbacks: {
label: function(tooltipItem, data) {
var label = data.datasets[tooltipItem.datasetIndex].label || '';
if (label) {
label += ': ';
}
label += tooltipItem.yLabel.noExponents();
return label;
}
}
}
},
});
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/Chart.js/2.7.3/Chart.min.js"></script>
<div style="width:75%;">
<canvas id="myChart"></canvas>
</div>
Related
Following on from the answer in this post
I have the following chart which can also be found here
const d0 = new Date("2023-02-15T00:00:00.721Z").getTime()
const d1 = new Date("2023-02-15T01:00:00.721Z").getTime()
const d2 = new Date("2023-02-15T02:30:00.721Z").getTime()
const d3 = new Date("2023-02-15T03:20:00.721Z").getTime()
const d4 = new Date("2023-02-15T05:05:00.721Z").getTime()
let values = [d0, d1, d2, d3, d4];
let data = {
labels: [''],
datasets: [{
label: 'up',
axis: 'y',
data: [d1],
backgroundColor: 'red',
},{
label: 'down',
axis: 'y',
data: [d2],
backgroundColor: 'yellow',
},{
label: 'out',
axis: 'y',
data: [d3],
backgroundColor: 'green',
},{
label: 'up',
axis: 'y',
data: [d4],
backgroundColor: 'red',
}
]
};
const config = {
data,
type: 'bar',
options:{
elements: {
bar: {
borderWidth: 0
}
},
ticks: {
display: true
},
interaction: {
mode: 'dataset'
},
tooltip: {
mode: 'dataset'
},
hover: {
mode: 'dataset'
},
onClick: function (e) {
// debugger;
var activePointLabel =
this.getElementsAtEventForMode(e, 'dataset', { intersect: true }, false)
alert(activePointLabel[0].datasetIndex);
}
,
plugins: {
legend: {
display: false,
},
title: {
display: false,
},
},
indexAxis: 'y',
responsive: true,
maintainAspectRatio: false,
scales: {
x: {
grid: {
display: true
},
min: d0,
ticks: {
callback: function(value, index, ticks) {
return moment(value).format('HH:mm');
}
},
// afterBuildTicks: axis => axis.ticks = values.map(v => ({ value: v }))
},
y: {
grid: {
display: false
},
stacked: true
},
}
}};
new Chart(document.getElementById("chart"), config);
This produces this...
]1
I would like to get rid of all the grids lines , except the ticks, but if I set the gird displays false the tick also disappear, and it also leave a border around the chart, etg something like
Is there a way to do this?
Just add border: {display: false}, to the scales configuration. (here is the link to the documentation)
...
scales: {
x: {
border: {
display: false,
},
...
},
...
}
...
Update added full running example:
const d0 = moment.duration('07:00:00').asMinutes();
const d1 = moment.duration('09:00:00').asMinutes();
const d2 = moment.duration('10:45:00').asMinutes();
const d3 = moment.duration('17:35:00').asMinutes();
const d4 = moment.duration('19:00:00').asMinutes();
let values = [d0, d1, d2, d3, d4];
let data = {
labels: [''],
datasets: [{
label: 'up',
axis: 'y',
data: [d1],
backgroundColor: 'red',
},{
label: 'down',
axis: 'y',
data: [d2],
backgroundColor: 'yellow',
},{
label: 'out',
axis: 'y',
data: [d3],
backgroundColor: 'green',
},{
label: 'up',
axis: 'y',
data: [d4],
backgroundColor: 'red',
}
]
};
const config = {
data,
type: 'bar',
options:{
plugins: {
tooltip: {
mode: 'dataset',
callbacks: {
label: function(item){
return moment().startOf('day').add({ minute: item.raw}).format('HH:mm');
}
}
},
legend: {
display: false,
},
title: {
display: false,
},
},
indexAxis: 'y',
responsive: true,
maintainAspectRatio: false,
scales: {
x: {
min: d0,
border: { display: false },
ticks: {
callback: function(value, index, ticks) {
return moment().startOf('day').add({ minute: value}).format('HH:mm');
}
},
afterBuildTicks: axis => axis.ticks = values.map(v => ({ value: v }))
},
y: {
stacked: true,
grid: { display: false },
},
}
}};
new Chart(document.getElementById("chart"), config);
<script src="//cdn.jsdelivr.net/npm/chart.js"></script>
<script src="//cdn.jsdelivr.net/npm/moment#^2"></script>
<script src="//cdn.jsdelivr.net/npm/chartjs-adapter-moment#^1"></script>
<div class="chart" style="height:84px; width:350px;">
<canvas id="chart" ></canvas>
</div>
use tickColor (see below config) for v 3.8.2
scales: {
x: {
...
grid: {
display: true,
drawTicks: true, //show ticks
borderColor: "transparent", //horizontal line color above ticks (x-axis)
color: "transparent", //grid lines color
tickColor: "#868e96" //ticks color (little line above points)
},
},
...
}
I have many bars with a thousand values like 35000, 12000, and 76560. So these values are getting overlapped with each other. I need to change Bar values not StepSize.
I want to show these values 35k, 12k and 76.5k format. This is my code
public barStatus() {
var colors = ['#299DFF', '#80FFFF', '#F8362B', ];
var chBar = document.getElementById("chBar");
var chartData = {
datasets: [{
label: 'Success',
data: [35000, 12000, 76560],
backgroundColor: colors[0]
}, ]
}
var barOptions_stacked = {
onClick: this.Status,
tooltips: {
enabled: true
},
plugins: {
datalabels: {
anchor: 'end',
align: 'left',
formatter: Math.round,
font: {
color: 'black'
}
},
},
hover: {
animationDuration: 0
},
scales: {
xAxes: [{
barPercentage: 0.5,
categoryPercentage: 0.5
}
],
yAxes: [{
gridLines: {
display: false
},
type: 'logarithmic',
position: 'left',
ticks: {
min: 0, //minimum tick
max: 100000, //maximum tick
callback: function (value, index, values) {
return Number(value.toString()); //pass tick values as a string into Number function
}
},
afterBuildTicks: function (chartObj) { //Build ticks labelling as per your need
chartObj.ticks = [];
chartObj.ticks.push(0);
chartObj.ticks.push(10);
chartObj.ticks.push(100);
chartObj.ticks.push(1000);
chartObj.ticks.push(10000);
chartObj.ticks.push(100000);
},
scaleLabel: {
display: false
},
stacked: false
}]
},
};
this.Canvas = document.getElementById("chBar");
this.chart = new Chart(this.Canvas, {
type: "bar",
data: chartData,
options: barOptions_stacked
});
}
How can I do that?
Screenshot:
You need to pass a function in formatter option inside datalabels plugin configuration:
datalabels: {
anchor: "end",
align: "left",
formatter: function(context) {
return context / 1000 + "k";
},
font: {
color: "black"
}
}
You can check the solution in this demo: https://stackblitz.com/edit/angular-chart-js-thousand?file=src/app/app.component.ts
For styling only the labels you want something like this:
var ctx = document.getElementById("myChart");
var myChart = new Chart(ctx, {
type: "line",
data: {
labels: ["Red", "Blue", "Yellow", "Green", "Purple", "Orange"],
datasets: [{
label: "# of Votes",
data: [12000, 1900, 3000, 5000, 2201, 3492]
}]
},
options: {
scales: {
yAxes: [{
ticks: {
beginAtZero: true
}
}]
}
}
});
setTimeout(function() {
myChart.options.scales = {
xAxes: [],
yAxes: [{
gridLines: {
display: false
},
type: 'logarithmic',
position: 'left',
ticks: {
min: 0, //minimum tick
max: 100000, //maximum tick
callback: function(value, index, values) {
return Number((value / 1000).toString()) + 'K'; //pass tick values as a string into Number function
}
},
afterBuildTicks: function(chartObj) { //Build ticks labelling as per your need
chartObj.ticks = [];
chartObj.ticks.push(0);
chartObj.ticks.push(10);
chartObj.ticks.push(100);
chartObj.ticks.push(1000);
chartObj.ticks.push(10000);
chartObj.ticks.push(100000);
},
scaleLabel: {
display: false
}
}]
};
myChart.update();
}, 1000);
.myChartDiv {
max-width: 600px;
max-height: 400px;
}
<script src="https://npmcdn.com/chart.js#latest/dist/Chart.bundle.js"></script>
<div class="myChartDiv">
<canvas id="myChart" width="600" height="400"></canvas>
</div>
In case you want to change the format of the value shown when hovering the chart and displaying the value inside the tooltip, you need to use the tooltip callbacks.
For example:
var ctx = document.getElementById("myChart");
var myChart = new Chart(ctx, {
type: "line",
data: {
labels: ["Red", "Blue", "Yellow", "Green", "Purple", "Orange"],
datasets: [
{
label: "# of Votes",
data: [12000, 1900, 3000, 5000, 2201, 3492]
}
]
},
options: {
tooltips: {
callbacks: {
label: function(tooltipItem, data) {
return (tooltipItem.yLabel/1000)+'K';
}
}
},
scales: {
yAxes: [
{
ticks: {
beginAtZero: true
}
}
]
}
}
});
setTimeout(function() {
myChart.options.scales = {
xAxes: [],
yAxes: [ {
gridLines: {
display: false
},
type: 'logarithmic',
position: 'left',
ticks: {
min: 0, //minimum tick
max: 100000, //maximum tick
callback: function (value, index, values) {
return Number((value/1000).toString())+'K'; //pass tick values as a string into Number function
}
},
afterBuildTicks: function (chartObj) { //Build ticks labelling as per your need
chartObj.ticks = [];
chartObj.ticks.push(0);
chartObj.ticks.push(10);
chartObj.ticks.push(100);
chartObj.ticks.push(1000);
chartObj.ticks.push(10000);
chartObj.ticks.push(100000);
},
scaleLabel: {
display: false
}
}
]
};
myChart.update();
}, 1000);
.myChartDiv {
max-width: 600px;
max-height: 400px;
}
<script src="https://npmcdn.com/chart.js#latest/dist/Chart.bundle.js"></script>
<div class="myChartDiv">
<canvas id="myChart" width="600" height="400"></canvas>
</div>
Last example involves the plugin you use in your question.
var ctx = document.getElementById("myChart");
var myChart = new Chart(ctx, {
type: "line",
data: {
labels: ["Red", "Blue", "Yellow", "Green", "Purple", "Orange"],
datasets: [{
datalabels: {
color: '#000'
},
label: "# of Votes",
data: [12000, 1900, 3000, 5000, 2201, 3492]
}]
},
options: {
plugins: {
datalabels: {
color: '#000',
formatter: function(value, context) {
return context.chart.data.labels[context.dataIndex] + ': ' + Math.round(value / 1000) + 'K';
}
}
},
tooltips: {
callbacks: {
label: function(tooltipItem, data) {
return (tooltipItem.yLabel / 1000) + 'K';
}
}
},
scales: {
yAxes: [{
ticks: {
beginAtZero: true
}
}]
}
}
});
setTimeout(function() {
myChart.options.scales = {
xAxes: [],
yAxes: [{
gridLines: {
display: false
},
type: 'logarithmic',
position: 'left',
ticks: {
min: 0, //minimum tick
max: 100000, //maximum tick
callback: function(value, index, values) {
return Number((value / 1000).toString()) + 'K'; //pass tick values as a string into Number function
}
},
afterBuildTicks: function(chartObj) { //Build ticks labelling as per your need
chartObj.ticks = [];
chartObj.ticks.push(0);
chartObj.ticks.push(10);
chartObj.ticks.push(100);
chartObj.ticks.push(1000);
chartObj.ticks.push(10000);
chartObj.ticks.push(100000);
},
scaleLabel: {
display: false
}
}]
};
myChart.update();
}, 1000);
.myChartDiv {
max-width: 600px;
max-height: 400px;
}
<script src="https://npmcdn.com/chart.js#latest/dist/Chart.bundle.js"></script>
<script src="https://cdn.jsdelivr.net/npm/chartjs-plugin-datalabels"></script>
<div class="myChartDiv">
<canvas id="myChart" width="600" height="400"></canvas>
</div>
I have found the solution (just now). In config option its will have animation and call back with function onComplete. Here you can draw the label with any format you want. Please see this picture for code
Small data isn't visible for doughnut chart type. Can i resize it without change label value?
My chart options:
options: {
cutoutPercentage: 65,
maintainAspectRatio: false,
legend: {
display: false
},
plugins: {
datalabels: {
display: false
}
},
tooltips: {
enabled: true,
mode: 'nearest'
},
scales: {
yAxes: [{
ticks: {
max: 5,
min: 0,
stepSize: 0.5
}
}]
}
}
Example:
http://jsfiddle.net/Lkya2tqb/
I converted the dataset to percent and round a small value to 1.
var seriesData = [1,210,215];
var total = seriesData.reduce((a,v) => a + v);
var inPercent = seriesData.map(v => Math.max(v / total * 100, 1));
Create callback for tooltip.
tooltips: {
callbacks: {
label: function(tooltipItem, data) {
var value = seriesData[tooltipItem.index];
var label = data.labels[tooltipItem.index];
return `${label}: ${value}`;
}
}
var seriesData = [1, 210, 215];
var total = seriesData.reduce((a, v) => a + v);
var inPercent = seriesData.map(v => Math.max(v / total * 100, 1));
var labelsData = ["one", "two", "second"];
var backgroundColors = ["#FBC02D", "#E64A19", "#388E3C"]
var t = new Chart(document.getElementById('broadcast').getContext('2d'), {
type: "doughnut",
data: {
datasets: [{
data: inPercent,
backgroundColor: backgroundColors,
hoverBorderColor: "#fff"
}],
labels: labelsData,
},
options: {
cutoutPercentage: 65,
maintainAspectRatio: false,
legend: {
display: false
},
plugins: {
datalabels: {
display: false
}
},
tooltips: {
enabled: true,
mode: 'nearest',
callbacks: {
label: function(tooltipItem, data) {
var value = seriesData[tooltipItem.index];
var label = labelsData[tooltipItem.index];
return `${label}: ${value}`;
}
}
}
}
});
<script src="https://cdn.jsdelivr.net/npm/chart.js"></script>
<canvas id="broadcast" width="350" height="250" style="width: 350px; height: 250px;"></canvas>
I am attempting to use the charts.js plug-in and do a combo chart, but I want the line to be on top of the bar. This is the syntax that I am using, and both my arrays linedata & bardata are populated but whenever I run this syntax I get an error of
Uncaught TypeError: Cannot read property 'concat' of undefined
at n (Chart.min.js:11)
at t.update (Chart.min.js:11)
at t.construct (Chart.min.js:11)
at new t (Chart.min.js:12)
at trends:507
This is the syntax I utulize - where is the error?
var ctx = document.getElementById('canvas').getContext('2d');
var chart = new Chart(ctx, {
data: {
labels: labelsarr,
datasets: [{
type: 'line',
fill: false,
label: 'Line Example',
backgroundColor: 'rgba(255,0,0,1)',
borderColor: 'rgba(255,0,0,1)',
data: linedata
}, {
type: 'bar',
label: 'Bar Example',
backgroundColor: 'rgba(0, 129, 214, 0.8)',
data: bardata
}]
},
options: {
tooltips: {
callbacks: {
label: function (t, d) {
var xLabel = d.datasets[t.datasetIndex].label;
var yLabel = t.yLabel >= 1000 ? '$' + t.yLabel.toString().replace(/\B(?=(\d{3})+(?!\d))/g, ",") : '$' + t.yLabel;
return xLabel + ': ' + yLabel;
}
}
},
legend: {
display: false,
position: 'top',
},
scales: {
yAxes: [{
ticks: {
beginAtZero: true,
callback: function (value, index, values) {
if (parseInt(value) >= 1000) {
return '$' + value.toString().replace(/\B(?=(\d{3})+(?!\d))/g, ",");
} else {
return '$' + value;
}
}
}
}]
}
},
plugins: [{
beforeDraw: function(chart) {
var labels = chart.data.labels;
}
}]
});
Edit
This is how the arrays are being populated - values passed from php
var ldata = <?php echo $ldata; ?>;
var values = [];
for (var i = 0; i < ldata.length; i++) {
values.push(ldata[i]);
}
var bdata = <?php echo $bdata; ?>;
var values1 = [];
for (var i = 0; i < bdata.length; i++) {
values1.push(bdata[i]);
}
You would have to set the chart type in the main chart option, not inside the dataset (the second one) :
var chart = new Chart(ctx, {
type: 'bar',
data: {
...
Here is the working version of your code :
var labelsarr = ['A', 'B', 'C'];
var linedata = [2, 5, 3];
var bardata = [4, 2, 6];
var ctx = document.getElementById('canvas').getContext('2d');
var chart = new Chart(ctx, {
type: 'bar', //<-- set here
data: {
labels: labelsarr,
datasets: [{
type: 'line',
fill: false,
label: 'Line Example',
backgroundColor: 'rgba(255,0,0,1)',
borderColor: 'rgba(255,0,0,1)',
data: linedata
}, {
label: 'Bar Example',
backgroundColor: 'rgba(0, 129, 214, 0.8)',
data: bardata
}]
},
options: {
tooltips: {
callbacks: {
label: function(t, d) {
var xLabel = d.datasets[t.datasetIndex].label;
var yLabel = t.yLabel >= 1000 ? '$' + t.yLabel.toString().replace(/\B(?=(\d{3})+(?!\d))/g, ",") : '$' + t.yLabel;
return xLabel + ': ' + yLabel;
}
}
},
legend: {
display: false,
position: 'top',
},
scales: {
yAxes: [{
ticks: {
beginAtZero: true,
callback: function(value, index, values) {
if (parseInt(value) >= 1000) {
return '$' + value.toString().replace(/\B(?=(\d{3})+(?!\d))/g, ",");
} else {
return '$' + value;
}
}
}
}]
}
},
plugins: [{
beforeDraw: function(chart) {
var labels = chart.data.labels;
}
}]
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/Chart.js/2.6.0/Chart.min.js"></script>
<canvas id="canvas"></canvas>
is there any way to do a stacked and grouped bar chart with Chart.js library?
It should look something like this http://www.highcharts.com/demo/column-stacked-and-grouped
OK, I found the solution. It's described in this GitHub issue and solution is in this JSFiddle
Chart.defaults.groupableBar = Chart.helpers.clone(Chart.defaults.bar);
var helpers = Chart.helpers;
Chart.controllers.groupableBar = Chart.controllers.bar.extend({
calculateBarX: function (index, datasetIndex) {
// position the bars based on the stack index
var stackIndex = this.getMeta().stackIndex;
return Chart.controllers.bar.prototype.calculateBarX.apply(this, [index, stackIndex]);
},
hideOtherStacks: function (datasetIndex) {
var meta = this.getMeta();
var stackIndex = meta.stackIndex;
this.hiddens = [];
for (var i = 0; i < datasetIndex; i++) {
var dsMeta = this.chart.getDatasetMeta(i);
if (dsMeta.stackIndex !== stackIndex) {
this.hiddens.push(dsMeta.hidden);
dsMeta.hidden = true;
}
}
},
unhideOtherStacks: function (datasetIndex) {
var meta = this.getMeta();
var stackIndex = meta.stackIndex;
for (var i = 0; i < datasetIndex; i++) {
var dsMeta = this.chart.getDatasetMeta(i);
if (dsMeta.stackIndex !== stackIndex) {
dsMeta.hidden = this.hiddens.unshift();
}
}
},
calculateBarY: function (index, datasetIndex) {
this.hideOtherStacks(datasetIndex);
var barY = Chart.controllers.bar.prototype.calculateBarY.apply(this, [index, datasetIndex]);
this.unhideOtherStacks(datasetIndex);
return barY;
},
calculateBarBase: function (datasetIndex, index) {
this.hideOtherStacks(datasetIndex);
var barBase = Chart.controllers.bar.prototype.calculateBarBase.apply(this, [datasetIndex, index]);
this.unhideOtherStacks(datasetIndex);
return barBase;
},
getBarCount: function () {
var stacks = [];
// put the stack index in the dataset meta
Chart.helpers.each(this.chart.data.datasets, function (dataset, datasetIndex) {
var meta = this.chart.getDatasetMeta(datasetIndex);
if (meta.bar && this.chart.isDatasetVisible(datasetIndex)) {
var stackIndex = stacks.indexOf(dataset.stack);
if (stackIndex === -1) {
stackIndex = stacks.length;
stacks.push(dataset.stack);
}
meta.stackIndex = stackIndex;
}
}, this);
this.getMeta().stacks = stacks;
return stacks.length;
},
});
var data = {
labels: ["January", "February", "March"],
datasets: [
{
label: "Apples",
backgroundColor: "rgba(99,255,132,0.2)",
data: [20, 10, 30],
stack: 1
},
{
label: "Bananas",
backgroundColor: "rgba(99,132,255,0.2)",
data: [40, 50, 20],
stack: 1
},
{
label: "Cookies",
backgroundColor: "rgba(255,99,132,0.2)",
data: [60, 20, 20],
stack: 1
},
{
label: "Apples",
backgroundColor: "rgba(99,255,132,0.2)",
data: [20, 10, 30],
stack: 2
},
{
label: "Bananas",
backgroundColor: "rgba(99,132,255,0.2)",
data: [40, 50, 20],
stack: 2
},
{
label: "Cookies",
backgroundColor: "rgba(255,99,132,0.2)",
data: [60, 20, 20],
stack: 2
},
{
label: "Apples",
backgroundColor: "rgba(99,255,132,0.2)",
data: [20, 10, 30],
stack: 3
},
{
label: "Bananas",
backgroundColor: "rgba(99,132,255,0.2)",
data: [40, 50, 20],
stack: 3
},
{
label: "Cookies",
backgroundColor: "rgba(255,99,132,0.2)",
data: [60, 20, 20],
stack: 3
},
]
};
var ctx = document.getElementById("myChart").getContext("2d");
new Chart(ctx, {
type: 'groupableBar',
data: data,
options: {
legend: {
labels: {
generateLabels: function(chart) {
return Chart.defaults.global.legend.labels.generateLabels.apply(this, [chart]).filter(function(item, i){
return i <= 2;
});
}
}
},
scales: {
yAxes: [{
ticks: {
max: 160,
},
stacked: true,
}]
}
}
});
You should use the stack property of the dataset object for each dataset.
As you can see in Chart.js Documentation, stack is defined as:
"The ID of the group to which this dataset belongs to (when stacked, each group will be a separate stack)"
I believe this functionality has been introduced recently and in 2016 Chart.js did not have this because of this post
You can acheive stacked bar chart with below data
this.dataStackedBarChart = {
type: 'horizontalBar',
labels: this.stackedBarChartLabel,
datasets: [
{
label: 'Success Count',
stack: 'Stack 0',
data: this.successCount,
backgroundColor: 'green'
},
{
label: 'FailureCount',
stack: 'Stack 0',
data: this.failureCount,
backgroundColor: 'red'
},
{
label: 'AvgDuration',
stack: 'Stack 1',
data: this.avgDuration,
backgroundColor: 'black'
},
{
label: 'MaxDuration',
stack: 'Stack 2',
data: this.maxDuration,
backgroundColor: 'orange'
},
{
label: 'MinDuration',
stack: 'Stack 3',
data: this.minDuration,
backgroundColor: 'pink'
}
],
borderWidth: 2
}
this.optionsStackedBarChart = {
tooltips: {
callbacks: {
label: function (tooltipItem, data) {
var label = this.uniqueApiPath[tooltipItem.index];
return label;
}
}
},
scales: {
xAxes: [
{
stacked: true,
display: true,
ticks: {
beginAtZero: true,
min: 0,
suggestedMin: 0
}
}
],
yAxes: [
{
stacked: true,
display: true,
ticks: {
beginAtZero: true,
min: 0,
suggestedMin: 0
}
}
]
}