B. Clay Shannon B. Clay Shannon - 2 months ago 16
Javascript Question

How can I get my Chart.JS bar chart to stack two data values together on each bar, and print a calculated value on each bar?

I'm creating a Chart.js bar chart like so:

HTML

<canvas id="priceComplianceBarChart" width="540" height="360"></canvas>


JQUERY

var barChartData = {
labels: ["Bix Produce", "Capitol City", "Charlies Portland", "Costa Fruit and Produce", "Get Fresh Sales", "Loffredo East", "Loffredo West", "Paragon", "Piazza Produce"],
datasets: [
{
fillColor: "rgba(220,220,220,0.5)",
strokeColor: "rgba(220,220,220,0.8)",
highlightFill: "rgba(220,220,220,0.75)",
highlightStroke: "rgba(220,220,220,1)",
data: [17724, 5565, 3806, 5925, 5721, 6635, 14080, 9027, 25553]
},
{
fillColor: "rgba(151,187,205,0.5)",
strokeColor: "rgba(151,187,205,0.8)",
highlightFill: "rgba(151,187,205,0.75)",
highlightStroke: "rgba(151,187,205,1)",
data: [17, 1, 18, 14, 3, 1, 5, 10, 1]
}
]
}

var ctxBarChart = document.getElementById("priceComplianceBarChart").getContext("2d");
var myBarChart = new Chart(ctxBarChart).Bar(barChartData);


That produces a chart that looks like this:

enter image description here

What I want instead, though, is the two side-by-side values to appear stacked onto the same bar, in different colors, and then a calculated value (% of the total which is represented by the predominant color) to be added as a label on each bar and appended to the legends, too (such as, "Bix Produce - 99.9%").

The appending of the val to the legend labels below the bars I can figure out myself, I'm sure, but how to stack the two values onto one bar, and how to add the label to the bars - I have no idea how to accomplish those objectives.

Answer

in order to achieve a stacked bar chart with chart js you can use this code http://codepen.io/anon/pen/ozzyJy. I have replaced the second data values array with some bigger values in order to illustrate the stacked bars, but it will work fine with any values:

var ctx = document.getElementById("myChart");
var myChart = new Chart(ctx, {
    type: 'bar',
    data: {
        labels: ["Bix Produce", "Capitol City", "Charlies Portland", "Costa Fruit and Produce", "Get Fresh Sales", "Loffredo East", "Loffredo West", "Paragon", "Piazza Produce"],
        datasets: [{
            backgroundColor: 'rgba(97, 188, 109, 0.2)',
            borderColor: 'rgba(97, 188, 109, .8)',
            data: [7000, 5565, 3806, 5925, 5721, 6635, 14080, 9027, 25553]
        }, {
            backgroundColor: 'rgba(236, 107, 86, 0.2)',
            borderColor: 'rgba(236, 107, 86, .8)',
            data: [17724, 2565, 1506, 3625, 3721, 4635, 7080, 4027, 12553]
            //data: [17, 1, 18, 14, 3, 1, 5, 10, 1]
        }]
    },
    options: {
        tooltips: {
            enabled: false
        },
        animation: {
            duration: 0,
            onComplete: function() {
                if (this.data.datasets.length === 2) {
                    var ctx = this.chart.ctx;
                    ctx.font = Chart.helpers.fontString(Chart.defaults.global.defaultFontSize, 'normal', Chart.defaults.global.defaultFontFamily);
                    ctx.fillStyle = this.chart.config.options.defaultFontColor;
                    ctx.textAlign = 'center';
                    ctx.textBaseline = 'bottom';
                    var firstDataSet = this.data.datasets[0];
                    var secondDataSet = this.data.datasets[1];
                    if (firstDataSet.length === secondDataSet.length) {
                        for (var i = 0; i < firstDataSet.data.length; i++) {
                            var firstModel = firstDataSet._meta[Object.keys(firstDataSet._meta)[0]].data[i]._model;
                            var secondModel = secondDataSet._meta[Object.keys(secondDataSet._meta)[0]].data[i]._model;
                            var total = firstDataSet.data[i] + secondDataSet.data[i];
                            if (firstDataSet.data[i] >= secondDataSet.data[i]) {
                                ctx.fillText((firstDataSet.data[i] * 100 / total).toFixed(2) + '%', firstModel.x, firstModel.y + 30);
                            }else{
                                ctx.fillText((secondDataSet.data[i] * 100 / total).toFixed(2) + '%', secondModel.x, secondModel.y + 30);
                            }
                        }
                    }
                }
            }
        },
        scales: {
            yAxes: [{
                ticks: {
                    beginAtZero: true
                },
                stacked: true
            }],
            xAxes: [{
                stacked: true,
            }]
        }
    }
 });
Comments