Chartjs-Chart.js Formatting dual axis and labels

0👍

You can extend the bar chart to do this


Preview

enter image description here


Script

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]);
    },

    // hide preceding datasets in groups other than the one we are in
    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;
            }
        }
    },

    // reverse hideOtherStacks
    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();
            }
        }
    },

    // we hide preceding datasets in groups other than the one we are in
    // we then rely on the normal stacked logic to do its magic
    calculateBarY: function (index, datasetIndex) {
        this.hideOtherStacks(datasetIndex);
        var barY = Chart.controllers.bar.prototype.calculateBarY.apply(this, [index, datasetIndex]);
        this.unhideOtherStacks(datasetIndex);
        return barY;
    },

    // similar to calculateBarY
    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;
    },
});

and then

    ...
    type: 'groupableBar',
    options: {
        scales: {
            yAxes: [{
                ticks: {
                    // we have to set this manually (or we could calculate it from our input data)
                    max: 160,
                },
                stacked: true,
            }]
        }
    }
});

Note that we don’t have any logic to set the y axis limits, we just hard code it. If you leave it unspecified, you’ll end up with the limits you get if all the bars were stacked in one group.


Fiddle – http://jsfiddle.net/4rjge8sk/

Leave a comment