Chart.js格式化双轴和标签

时间:2022-12-04 10:26:01

jsfiddle here.

First time using Chart.js and I cannot find an example with the whole code to review. I have the following data for 3 months to chart:

第一次使用Chart.js,我找不到要查看整个代码的示例。我有以下3个月的数据来图表:

Project hours billed, Project hours not billed (stacked bar, for each month)
Billed Amount, To Be Billed amount (stacked bar for each month)

I want to stack the hours and also the billing totals, and want two Y axis, one for hours, the other for dollars.

我想要计算小时数和计费总额,并且想要两个Y轴,一个是小时,另一个是美元。

I have got as far as this code, but it does not stack the hours or the invoiced amounts for each month. Also, I cannot seem to format either axis and the values in the labels to time and currency.

我已经得到了这个代码,但它没有堆积每个月的小时数或发票金额。此外,我似乎无法格式化任何轴和标签中的时间和货币值。

Is there an example you can point me to showing this. Thanks!

有没有一个例子可以指出我展示这个。谢谢!

var barChartData = {
    labels: ["January", "February", "March"],
    datasets: [{
            type: 'bar',
            label: 'Billed Hours',
            backgroundColor: "rgba(220,220,220,0.5)",
            yAxisID: "y-axis-1",
            data: [33.56, 68.45, 79.35]
        }, {
            type: 'bar',
            label: 'Non Billed Hours',
            backgroundColor: "rgba(222,220,220,0.5)",
            yAxisID: "y-axis-1",
            data: [3.50, 8.58, 7.53]
        }, {
            type: 'bar',
            label: 'Income',
            backgroundColor: "rgba(151,187,205,0.5)",
            yAxisID: "y-axis-2",
            data: [3800.00, 7565.65, 8500.96]
        }, {
            type: 'bar',
            label: 'Income',
            backgroundColor: "rgba(155,187,205,0.5)",
            yAxisID: "y-axis-2",
            data: [320.00, 780.65, 850.96]
        }]

};
var ctx = document.getElementById("projectHours").getContext("2d");
window.myBar = new Chart(ctx, {
    type: 'bar',
    data: barChartData,
    options: {
        responsive: true,
        hoverMode: 'label',
        hoverAnimationDuration: 400,
        stacked: true,
        title: {
            display: true,
            text: "Billed / Billable Project Summary"
        },
        scales: {
            yAxes: [{
                type: "linear", // only linear but allow scale type registration. This allows extensions to exist solely for log scale for instance
                display: true,
                position: "left",
                id: "y-axis-1",
            }, {
                type: "linear", // only linear but allow scale type registration. This allows extensions to exist solely for log scale for instance
                display: true,
                position: "right",
                id: "y-axis-2",
                gridLines: {
                    drawOnChartArea: false
                },
            }],
        },
        animation: {
            onComplete: function () {
                var ctx = this.chart.ctx;
                ctx.textAlign = "center";
                Chart.helpers.each(this.data.datasets.forEach(function (dataset) {
                    Chart.helpers.each(dataset.metaData.forEach(function (bar, index) {
                        ctx.fillText(dataset.data[index], bar._model.x, bar._model.y - 10);
                    }),this)
                }),this);
            }
        }
    }
});

1 个解决方案

#1


0  

You can extend the bar chart to do this

您可以扩展条形图来执行此操作


Preview

Chart.js格式化双轴和标签


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.

请注意,我们没有任何逻辑来设置y轴限制,我们只需对其进行硬编码。如果您未指定,如果所有条形图都堆叠在一个组中,您将获得限制。


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

小提琴 - http://jsfiddle.net/4rjge8sk/

#1


0  

You can extend the bar chart to do this

您可以扩展条形图来执行此操作


Preview

Chart.js格式化双轴和标签


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.

请注意,我们没有任何逻辑来设置y轴限制,我们只需对其进行硬编码。如果您未指定,如果所有条形图都堆叠在一个组中,您将获得限制。


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

小提琴 - http://jsfiddle.net/4rjge8sk/