Skip to content
Advertisement

How can I change background color of a specific area in my chart’s grid using Chart.js and Annotation?

I’m having some trouble trying to change the backgroundColor of a specific chart area between two yAxis ticks.This is what I have so far:

What I'm getting from my code

And this is what I wanted:

What I wanted

I’ve seen some similar posts about that and people recommend using Annotation to do this. I tried using it on my chart and it didn’t work. This is my first time building a chart with chart.js so I’m still learning. Here’s my code:

var profileChart = new Chart(ctx1, {
type: "line",
data: {
    labels: ["", "D", "I", "S", "C", ""],
    datasets:[{
        data: [],
        borderWidth: 1,
        pointBackgroundColor: "black",
        backgroundColor: "black",
        borderColor: "black",
        fill: false,
        lineTension: 0, 
        yAxisID: 'first-y-axis'
    },
    {
        yAxisID: 'third-y-axis'
    }],
},
options: {
    title: {
        display: true,
        text: 'Gráfico do Perfil DISC',
        fontSize: 20,
    },
    scales: {
        yAxes: [{
            id: 'first-y-axis',
            type: 'linear',
            gridLines: {
                drawOnChartArea: false
            },
            scaleLabel: {
                display: true,
                padding: '15px',
                labelString: 'Intensity'
              },
            ticks: {
                max: 28,
                min: 1,
                stepSize: 1
            }
        },
        {
            id: 'second-y-axis',
            type: 'linear',
            position: 'left',
            gridLines: {
                drawOnChartArea: true
            },
            ticks: {
                display: false,
                min: 1,
                max: 8,
                stepSize: 1
            }
        },
        {
            id: 'third-y-axis',
            position: 'right',
            type: 'linear',
            gridLines: {
                drawOnChartArea: false
            },
            scaleLabel: {
                display: true,
                padding: '10px',
                labelString: 'Segment'
              },
            ticks: {
                max: 7.5,
                min: 0.5,
                stepSize: 1
            },
            afterTickToLabelConversion: function(scaleInstance) {
                scaleInstance.ticks[0] = null;
                scaleInstance.ticks[scaleInstance.ticks.length - 1] = null;
                scaleInstance.ticksAsNumbers[0] = null;
                scaleInstance.ticksAsNumbers[scaleInstance.ticksAsNumbers.length - 1] = null;
              },
        }] 
    },
    legend: {
        display: false
    },
    tooltips: {
        callbacks: {
           label: function(tooltipItem) {
                  return tooltipItem.yLabel;
           }
        }
    }
},
annotation: {
    drawTime: "afterDraw",
    annotations: [{
        id: 'box1',
      type: 'box',
      yScaleID: 'second-y-axis',
      yMin: 12.5,
      yMax: 16.5,
      backgroundColor: 'grey',
    }]
  }
});

Advertisement

Answer

You can draw the rectangle directly on the canvas using the Plugin Core API. The API offers a range of hooks that may be used for performing custom code.

In your amended code below, I use the beforeDraw hook to draw the rectangle through CanvasRenderingContext2D.fillRect().

var profileChart = new Chart('canvas', {
  type: "line",
  plugins: [{
    beforeDraw: chart => {
      var ctx = chart.chart.ctx;
      var xAxis = chart.scales['x-axis-0'];
      var yAxis = chart.scales['first-y-axis'];       
      ctx.save();            
      ctx.fillStyle  = 'lightgray';
      ctx.beginPath();    
      var yTop = yAxis.getPixelForValue(16.5);
      var yBottom = yAxis.getPixelForValue(12.5);
      ctx.fillRect(xAxis.left, yTop, xAxis.right - xAxis.left, yBottom - yTop);
      ctx.stroke();            
      ctx.restore();
    }
  }],
  data: {
    labels: ["", "D", "I", "S", "C", ""],
    datasets: [{
        data: [,25.5, 8, 7.5, 11],
        borderWidth: 1,
        pointBackgroundColor: "black",
        backgroundColor: "black",
        borderColor: "black",
        fill: false,
        lineTension: 0,
        yAxisID: 'first-y-axis'
      },
      {
        yAxisID: 'third-y-axis'
      }
    ],
  },
  options: {
    title: {
      display: true,
      text: 'Gráfico do Perfil DISC',
      fontSize: 20,
    },
    scales: {
      yAxes: [{
          id: 'first-y-axis',
          type: 'linear',
          gridLines: {
            drawOnChartArea: false
          },
          scaleLabel: {
            display: true,
            padding: '15px',
            labelString: 'Intensity'
          },
          ticks: {
            max: 28,
            min: 1,
            stepSize: 1
          }
        },
        {
          id: 'second-y-axis',
          type: 'linear',
          position: 'left',
          gridLines: {
            drawOnChartArea: true
          },
          ticks: {
            display: false,
            min: 1,
            max: 8,
            stepSize: 1
          }
        },
        {
          id: 'third-y-axis',
          position: 'right',
          type: 'linear',
          gridLines: {
            drawOnChartArea: false
          },
          scaleLabel: {
            display: true,
            padding: '10px',
            labelString: 'Segment'
          },
          ticks: {
            max: 7.5,
            min: 0.5,
            stepSize: 1
          },
          afterTickToLabelConversion: function(scaleInstance) {
            scaleInstance.ticks[0] = null;
            scaleInstance.ticks[scaleInstance.ticks.length - 1] = null;
            scaleInstance.ticksAsNumbers[0] = null;
            scaleInstance.ticksAsNumbers[scaleInstance.ticksAsNumbers.length - 1] = null;
          },
        }
      ]
    },
    legend: {
      display: false
    },
    tooltips: {
      callbacks: {
        label: function(tooltipItem) {
          return tooltipItem.yLabel;
        }
      }
    }
  }
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/Chart.js/2.9.4/Chart.bundle.min.js"></script>
<canvas id="canvas" height="200">
User contributions licensed under: CC BY-SA
6 People found this is helpful
Advertisement