How to fix background gradiend on resize Chart.js / canvas

Viewed 957

I am using the react chart js for displaying Line chart.

My gradient background is broken on resize window screen, it becomes black:

enter image description here

How to make it work by changing the size of the screen?

This is the function that creates and generates a gradient:

export const getGradientBackground = (canvas) => {
    const ctx = canvas.getContext('2d');

    const gradient = ctx.createLinearGradient(
        canvas.width / 2,
        0,
        canvas.width / 2,
        canvas.height
    );

    gradient.addColorStop(0.1, 'rgba(0, 145, 148, 0.15)');
    gradient.addColorStop(0.2, 'rgba(0, 145, 148, 0.15)');
    gradient.addColorStop(0.3, 'rgba(0, 145, 148, 0.15)');
    gradient.addColorStop(0.4, 'rgba(255, 255, 255, 0.15)');
    gradient.addColorStop(0.5, 'rgba(255, 255, 255, 0.15)');
    gradient.addColorStop(0.6, 'rgba(255, 255, 255, 0.15)');
    gradient.addColorStop(0.7, 'rgba(255, 255, 255, 0.15)');
    gradient.addColorStop(0.8, 'rgba(255, 255, 255, 0.15)');
    gradient.addColorStop(0.9, 'rgba(255, 255, 255, 0.15)');
    gradient.addColorStop(1.0, 'rgba(255, 255, 255, 0.15)');

    ctx.fillStyle = gradient;
    ctx.fillRect(10, 10, 200, 100);

    return gradient;
};

Any comment is welcome

2 Answers

I followed the link provided by Chris W in the comment and implemented it with react-chartjs-2

...
      <Line
        type="line"
        data={data}
        options={options}
        plugins={[
          {
            beforeDraw: function (chart, args, options) {
              const ctx = chart.ctx;
              const canvas = chart.canvas;
              const chartArea = chart.chartArea;

              // Chart background
              var gradient = canvas
                .getContext("2d")
                .createLinearGradient(
                  canvas.width / 2,
                  0,
                  canvas.width / 2,
                  canvas.height
                );
              gradient.addColorStop(0.1, "rgba(0, 145, 148, 0.15)");
              gradient.addColorStop(0.2, "rgba(0, 145, 148, 0.15)");
              gradient.addColorStop(0.3, "rgba(0, 145, 148, 0.15)");
              gradient.addColorStop(0.4, "rgba(255, 255, 255, 0.15)");
              gradient.addColorStop(0.5, "rgba(255, 255, 255, 0.15)");
              gradient.addColorStop(0.6, "rgba(255, 255, 255, 0.15)");
              gradient.addColorStop(0.7, "rgba(255, 255, 255, 0.15)");
              gradient.addColorStop(0.8, "rgba(255, 255, 255, 0.15)");
              gradient.addColorStop(0.9, "rgba(255, 255, 255, 0.15)");
              gradient.addColorStop(1.0, "rgba(255, 255, 255, 0.15)");

              ctx.fillStyle = gradient;
              ctx.fillRect(
                chartArea.left,
                chartArea.bottom,
                chartArea.right - chartArea.left,
                chartArea.top - chartArea.bottom
              );
            }
          }
        ]}
      />
...

As you can see in this codesandbox, the background persists when you resize the screen. Probably the problem was that you were not taking into account the chart dimensions to calculate background rectangle dimensions

I had the same issue when I was using apexcharts.js(similar to Chart.js) I had to add background color to y-axis for that I used SVG(you can also do the same with canvas).

Due to appending an svg element dynamically or drawing a canvas if the window is resized it would make that element disappeared, for that I used resize event which would fire a function after 500ms to re-add that element.

This counter of 500 ms gets restarted whenever there is a change in the window's dimensions (as we clear the timeout) so the function will only be called if the user stops resizing the window or if the user resizes the window VERY slowly which doesn't happens normally.

This will work for you

var func;

window.addEventListener("resize", function(){
  clearTimeout(func);
func = setTimeout(getGradientBackground, 500);
})
Related