3

I have a react-chart-js2 component that I am trying to make a gradient on the fill however I am getting a few different typescript errors and cant seem to get it working.

The documentation says to pass the data prop as a function with a reference to the canvas in order to access the canvas context to add the gradient. Unfortunately this is not working.

Here is a codesandbox of the files: https://codesandbox.io/s/modest-bird-j2in8 (file LineChartGradient.tsx)

The errors I get surround the Canvas Context and passing a data function to the chartjs component

Data

const data = (canvas: HTMLCanvasElement) => {
    const ctx = canvas.getContext("2d");
    const gradient = ctx.createLinearGradient(0, 0, 0, 200);
    gradient.addColorStop(0, "rgba(250,174,50,1)");
    gradient.addColorStop(1, "rgba(250,174,50,0)");

    return {
      labels: ["Jan", "Feb", "Mar", "Apr", "May", "Jun"],
      datasets: [
        {
          label: "First dataset",
          data: [33, 53, 85, 41, 44, 65],
          fill: "start",
          backgroundColor: "rgba(75,192,192,0.2)",
          borderColor: "rgba(75,192,192,1)"
        },
        {
          label: "Second dataset",
          data: [33, 25, 35, 51, 54, 76],
          fill: "start",
          borderColor: "#742774"
        }
      ]
    };
  };

Component

  return (
    <div>
      <Line data={data} options={options} />
    </div>
  );

Error #1

const gradient = ctx.createLinearGradient(0, 0, 0, 200);

Typescript saying that this object could possible be null, this is fine I can check if it exists but it is my first clue that the canvas element is not being passed

Error #2

<Line data={data} options={options} />

Property 'datasets' is missing in type '(canvas: HTMLCanvasElement) => { labels: string[]; datasets:

When passing the data as a function I get this error however if I just drop the object that is returned by the data function inside the data prop the graph renders fine (See LineChart.tsx).

What is the correct way of accessing the canvas context in react-chartjs-2 to add a gradient fill?

Jason McFarlane
  • 2,048
  • 3
  • 18
  • 30

2 Answers2

15

This is because you dont pass any canvas to the data function when you call it in

<Line data={data} options={options} />

But the canvas is also not availabale here. If you want to make a custom gradient you will need to apply a scriptable option for the backgroundColor like so:

const data = () => {
  return {
    labels: ["Jan", "Feb", "Mar", "Apr", "May", "Jun"],
    datasets: [{
      label: "First dataset",
      data: [33, 53, 85, 41, 44, 65],
      fill: "start",
      backgroundColor: (context: ScriptableContext<"line">) => {
        const ctx = context.chart.ctx;
        const gradient = ctx.createLinearGradient(0, 0, 0, 200);
        gradient.addColorStop(0, "rgba(250,174,50,1)");
        gradient.addColorStop(1, "rgba(250,174,50,0)");
        return gradient;
      },
      borderColor: "rgba(75,192,192,1)"
    }]
  };
};

Also make sure to call the function in your data field so your html becomes this:

<Line data={data()} options={options} />

Working Codesandbox: https://codesandbox.io/s/interesting-faraday-204ugi?file=/src/LineChartGradient.tsx

LeeLenalee
  • 27,463
  • 6
  • 45
  • 69
-1

so it's look that there is a lot of errors with your code , i'm trying to help by solving the second problem , data should be json not a function so to solve this you should to execute the function before pass it like this :

<Line data={data()} options={options} />

  
  export default function Chart(){
    return (
    <div>
    {
    /****
    pass data() not data
    ****/
    }
      <Line data={data()} options={options} />
    </div>
  );
  }
Fiber X01
  • 31
  • 1
  • 4
  • ive tried this before this isnt it, this also fires off the data function immediately instead of passing it as a prop where it should then be passed context from chartjs lib – Jason McFarlane Feb 11 '22 at 23:53
  • you tried execute it outside and assign it to a variable then pass it ? – Fiber X01 Feb 12 '22 at 00:04
  • This is not correct. Data also accepts a function that importantly has the html canvas element as the first parameter, making things like what OP is asking about significantly easier. – Lars Holdaas Sep 01 '22 at 00:33