javascriptcsschart.jschartjs-2.6.0

Chartjs color the background of chart after specific values with dark grey color


I am new to ChartJS and due to server constraints I am using ChartJS 2.9.4 using cdnjs and I want to color the background of line chart from

  1. 60-80 ==> light grey with background text in right side as Significant with dotted lines
  2. 80-100 ==> dark grey with background text in right side as Severe

Currently it is like this: enter image description here

And the requirement is this: enter image description here

Below is the implemented code:

var ctx = document.getElementById("lineChart").getContext("2d");
      var chart = new Chart(ctx, {
        type: "line",
        data: {
          labels: [
            "",
            "Working Memory",
            "Inhibitory Control",
            "Cognitive Flexibility",
            "High Order EF",
            "",
          ],
          datasets: [
            {
              label: "Competence score in Percent",
              data: [null, 80, 65, 90, 75],
              borderColor: ["#000", "#ffdb14", "#ff0000", "#38b7fe", "#8866f9"],
              backgroundColor: [
                "#000",
                "#ffdb14",
                "#ff0000",
                "#38b7fe",
                "#8866f9",
              ],
              fill: false,
              pointRadius: 16,
              pointHoverRadius: 8,
              pointBackgroundColor: [
                "#000",
                "#ffdb14",
                "#ff0000",
                "#38b7fe",
                "#8866f9",
              ],
              lineTension: 0,
              borderColor: "#000",
              borderWidth: 2,
            },
          ],
        },
        options: {
          responsive: true,
          scales: {
            xAxes: [
              {
                scaleLabel: {
                  display: true,
                  labelString: "Subtests",
                  fontSize: 24,
                },
                ticks: {
                  fontSize: 24,
                },
              },
            ],
            yAxes: [
              {
                scaleLabel: {
                  display: true,
                  labelString: "Competence score in Percent",
                  fontSize: 24,
                },
                ticks: {
                  beginAtZero: true,
                  min: 0,
                  max: 100,
                  stepSize: 25,
                  fontSize: 24,
                },
              },
            ],
          },
          legend: {
            display: false,
          },
        },
      });

Solution

  • One way to go is to try using chartjs-plugin-annotation whose version 0.5.7 should work with chart.js version 2.x

    You'd use a box annotation and a text annotation for each band.

    If your restrictions don't even allow to use that, and since your drawings are quite specific, you can implement yourself a plugin to draw the bands.

    The plugin should implement the method beforeDraw, and get hold of the drawing context and the axes through it chart first argument. Those would very simply allow you to draw anywhere on the canvas before the chart is drawn:

    plugins:[{
        beforeDraw(chart){
            const ctx = chart.ctx,
                xAxis = chart.scales['x-axis-0'],
                xMin = xAxis.left,
                xMax = xAxis.right,
                yAxis = chart.scales['y-axis-0'],
                y100 = yAxis.getPixelForValue(100),
                y80 = yAxis.getPixelForValue(80),
                y60 = yAxis.getPixelForValue(60);
        
            // draw with these ...........
        }
    }]
    

    Here's a snippet implementing a possible solution:

    var ctx = document.getElementById("lineChart").getContext("2d");
    var chart = new Chart(ctx, {
        type: "line",
        plugins:[{
            beforeDraw(chart){
                const ctx = chart.ctx,
                    xAxis = chart.scales['x-axis-0'],
                    xMin = xAxis.left,
                    xMax = xAxis.right,
                    yAxis = chart.scales['y-axis-0'],
                    y100 = yAxis.getPixelForValue(100),
                    y80 = yAxis.getPixelForValue(80),
                    y60 = yAxis.getPixelForValue(60);
                
                for(var [yMin, yMax, color, text] of
                    [[y60, y80, 'rgba(200, 200, 200, 0.8)', 'Significant'],
                        [y80, y100, 'rgba(100, 100, 100, 0.8)', 'Severe']]){
                    ctx.fillStyle = color;
                    ctx.fillRect(xMin, yMin, xMax-xMin, yMax-yMin);
                    ctx.fillStyle = '#fff';
                    ctx.strokeStyle = 'rgba(0,0,0,0.3)';
                    ctx.textAlign = 'right';
                    ctx.font = Math.round(Math.min((yMax-yMin)/3, 48))+'px serif';
                    ctx.textBaseline = 'middle';
                    ctx.fillText(text, xMax-10,(yMax+yMin)/2)
                    ctx.strokeText(text, xMax-10,(yMax+yMin)/2)
                }
            }
        }],
        data: {
            labels: [
                "",
                "Working Memory",
                "Inhibitory Control",
                "Cognitive Flexibility",
                "High Order EF",
                "",
            ],
            datasets: [
                {
                    label: "Competence score in Percent",
                    data: [null, 80, 65, 90, 75],
                    borderColor: ["#000", "#ffdb14", "#ff0000", "#38b7fe", "#8866f9"],
                    backgroundColor: [
                        "#000",
                        "#ffdb14",
                        "#ff0000",
                        "#38b7fe",
                        "#8866f9",
                    ],
                    fill: false,
                    pointRadius: 16,
                    pointHoverRadius: 8,
                    pointBackgroundColor: [
                        "#000",
                        "#ffdb14",
                        "#ff0000",
                        "#38b7fe",
                        "#8866f9",
                    ],
                    lineTension: 0,
                    borderColor: "#000",
                    borderWidth: 2,
                },
            ],
        },
        options: {
            responsive: true,
            scales: {
                xAxes: [
                    {
                        scaleLabel: {
                            display: true,
                            labelString: "Subtests",
                            fontSize: 24,
                        },
                        ticks: {
                            fontSize: 24,
                        },
                    },
                ],
                yAxes: [
                    {
                        scaleLabel: {
                            display: true,
                            labelString: "Competence score in Percent",
                            fontSize: 24,
                        },
                        ticks: {
                            beginAtZero: true,
                            min: 0,
                            max: 100,
                            stepSize: 25,
                            fontSize: 24,
                        },
                    },
                ],
            },
            legend: {
                display: false,
            },
        },
    });
    <canvas id="lineChart" style="width:99vw; height: 99vh"></canvas>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/Chart.js/2.9.4/Chart.bundle.js" integrity="sha512-zO8oeHCxetPn1Hd9PdDleg5Tw1bAaP0YmNvPY8CwcRyUk7d7/+nyElmFrB6f7vg4f7Fv4sui1mcep8RIEShczg==" crossorigin="anonymous" referrerpolicy="no-referrer"></script>

    or jsFiddle