[Chartjs]-Chart JS — Conditional horizontal row background colours

3👍

There is no option to do this with chartjs. However you can write your own plugin and draw the background by yourself in the beforeDraw hook for example.

var chart = new Chart(ctx, {
    plugins: [{
        beforeDraw: function(chart) {
            //..
        }
    }]
});

You can get all the information to calculate the height of an y-axis-segment from the chart parameter.
I’ve included a snippet below how this could be implemented. Note however that this is more a proof of concept than a proper implementation:

        var canvas = document.getElementById('myChart');
        window.chartColors = {
            red: 'rgb(255, 99, 132)',
            orange: 'rgb(255, 159, 64)',
            yellow: 'rgb(255, 205, 86)',
            green: 'rgb(51, 204, 51)',
            blue: 'rgb(54, 162, 235)',
            purple: 'rgb(153, 102, 255)',
            grey: 'rgb(201, 203, 207)'
        };

        var myLineChart = new Chart(canvas,
            {
                type: 'line',
                data: {
                    labels: ['1', '2', '3', '4', '5'],
                    datasets: [
                        {
                            label: '# of Votes',
                            fill: false,
                            backgroundColor: window.chartColors.blue,
                            borderColor: window.chartColors.blue,
                            data: [2, 5, 12.5, 9, 6.3]
                        }
                    ]
                },
                options: {
                    responsive: true,
                    title: {
                        display: true,
                        text: 'Conditional Background'
                    },
                    backgroundRules: [{
                        backgroundColor: window.chartColors.green, 
                        yAxisSegement: 6
                    }, {
                        backgroundColor: window.chartColors.grey,
                        yAxisSegement: 12
                    }, {
                        backgroundColor: window.chartColors.red,
                        yAxisSegement: Infinity
                    }],
                    scales: {
                        yAxes: [{
                            ticks: {
                                beginAtZero: true,
                                stepSize: 1
                            }
                        }]
                    }
                },
                plugins: [{
                    beforeDraw: function (chart) {
                        var ctx = chart.chart.ctx;
                        var ruleIndex = 0;
                        var rules = chart.chart.options.backgroundRules;
                        var yaxis = chart.chart.scales["y-axis-0"];
                        var xaxis = chart.chart.scales["x-axis-0"];
                        var partPercentage = 1 / (yaxis.ticksAsNumbers.length - 1);
                        for (var i = yaxis.ticksAsNumbers.length - 1; i > 0; i--) {
                            if (yaxis.ticksAsNumbers[i] < rules[ruleIndex].yAxisSegement) {
                                ctx.fillStyle = rules[ruleIndex].backgroundColor;
                                ctx.fillRect(xaxis.left, yaxis.top + ((i - 1) * (yaxis.height * partPercentage)), xaxis.width, yaxis.height * partPercentage);
                            } else {
                                ruleIndex++;
                                i++;
                            }
                        }
                    }
                }]
            });
<script src="https://cdnjs.cloudflare.com/ajax/libs/Chart.js/2.7.1/Chart.min.js"></script>
<canvas id="myChart" width="400" height="250"></canvas>

1👍

Shiffty’s answer is right on point, however it only works if the background values are present on the yAxis, which is not always the case… depends on what fits. A more generic solution is to calculate the actual values:

    var canvas = document.getElementById('myChart');
    window.chartColors = {
        red: 'rgb(255, 99, 132)',
        orange: 'rgb(255, 159, 64)',
        yellow: 'rgb(255, 205, 86)',
        green: 'rgb(51, 204, 51)',
        blue: 'rgb(54, 162, 235)',
        purple: 'rgb(153, 102, 255)',
        grey: 'rgb(201, 203, 207)'
    };

    var myLineChart = new Chart(canvas,
        {
            type: 'line',
            data: {
                labels: ['1', '2', '3', '4', '5'],
                datasets: [
                    {
                        label: '# of Votes',
                        fill: false,
                        backgroundColor: window.chartColors.blue,
                        borderColor: window.chartColors.blue,
                        data: [2, 5, 12.5, 9, 6.3]
                    }
                ]
            },
            options: {
                responsive: true,
                title: {
                    display: true,
                    text: 'Conditional Background'
                },
                backgroundRules: [{
                    backgroundColor: window.chartColors.green, 
                    yAxisSegement: 6
                }, {
                    backgroundColor: window.chartColors.grey,
                    yAxisSegement: 12
                }, {
                    backgroundColor: window.chartColors.red,
                    yAxisSegement: 999999
                }],
                scales: {
                    yAxes: [{
                        ticks: {
                            beginAtZero: true,
                            stepSize: 1
                        }
                    }]
                }
            },
            plugins: [{
                beforeDraw: function (chart) {
                    var rules = chart.chart.options.backgroundRules;
                    var ctx = chart.chart.ctx;
                    var yAxis = chart.chart.scales["y-axis-0"];
                    var xaxis = chart.chart.scales["x-axis-0"];
                    for (var i = 0; i < rules.length; ++i) {
                        var yAxisSegement = (rules[i].yAxisSegement > yAxis.ticksAsNumbers[0] ? yAxis.ticksAsNumbers[0] : rules[i].yAxisSegement);
                        var yAxisPosStart = yAxis.height - ((yAxisSegement * yAxis.height) / yAxis.ticksAsNumbers[0]) + chart.chart.controller.chartArea.top;
                        var yAxisPosEnd = (i === 0 ? yAxis.height : yAxis.height - ((rules[i - 1].yAxisSegement * yAxis.height) / yAxis.ticksAsNumbers[0]));
                        ctx.fillStyle = rules[i].backgroundColor;
                        ctx.fillRect(xaxis.left, yAxisPosStart, xaxis.width, yAxisPosEnd - yAxisPosStart + chart.chart.controller.chartArea.top);
                    }
                }
            }]
        });

Leave a comment