[Chartjs]-Chartjs: Is it possible to add phases in line chart?

4👍

Using Chart.js plugins can help you with this. They let you handle specific events that are triggered during the chart creation like beforeInit, afterUpdate or afterDraw and are also easy to implement :

var myPlugin = {
    afterDraw: function(chart) {
        // This will be triggered after the chart is drawn
    }
};

Chart.pluginService.register(myPlugin);

A plugin doing what you are looking for will be linked below, but first let me explain how it works.

In your chart options, you’ll need to add a new property, called phases, which is an array :

// The following is an example that won't work with every chart

options: {
    scales: {
        xAxes: [{

            // `from` & `to` must exist in your xAxe ticks
            phases: [{
                from: "January",
                to: "March",
                // You can also define the color here
                color: "blue"
            },
            {
                from: "May",
                to: "June",
                color: "red"
            }]
        }]
    }
}

And then, here is the plugin that use this information :

var phasePlugin = {
    // You need to handle the `afterDraw` event since you draw phases edges
    // after everything is drawn
    afterDraw: function(chart) 
    {
        // All the variables the plugin needs follow ...
        var ctx = chart.chart.ctx;
        var xAxeId = chart.config.options.scales.xAxes[0].id;
        var xAxe = chart.scales[xAxeId];
        var yAxeId = chart.config.options.scales.yAxes[0].id;
        var yAxe = chart.scales[yAxeId];
        var ticks = xAxe.ticks;
        var phases = chart.config.options.scales.xAxes[0].phases;

        // For every phase ...
        for (var i = 0; i < phases.length; i++) {

            // We check if the tick actually exists
            if (ticks.indexOf(phases[i].from) == -1 || (ticks.indexOf(phases[i].to) == -1)) {
                // Else, we skip to the next phase
                continue;
            }

            // We get the x position of the first limit tick
            var xPos = ((xAxe.width - xAxe.paddingRight) / xAxe.maxIndex) * ticks.indexOf(phases[i].from) + xAxe.left + 1;

            // And draw the dashed line
            ctx.setLineDash([8, 8]);
            ctx.strokeStyle = phases[i].color;
            ctx.strokeRect(xPos, yAxe.top, 0, yAxe.height);

            // Same for the other limit
            xPos = ((xAxe.width - xAxe.paddingRight) / xAxe.maxIndex) * ticks.indexOf(phases[i].to) + xAxe.left + 1;
            ctx.strokeStyle = phases[i].color;
            ctx.strokeRect(xPos, yAxe.top, 0, yAxe.height);
            ctx.setLineDash([1,0]);
        }
    }
};

You can see a fully working example in this jsFiddle and here is its result :

enter image description here

Leave a comment