【问题标题】:React-chartjs-2 gradient fill error on canvas context画布上下文中的 React-chartjs-2 渐变填充错误
【发布时间】:2023-01-20 09:03:29
【问题描述】:

我有一个 react-chart-js2 组件,我试图在填充上制作渐变,但是我遇到了一些不同的打字稿错误,似乎无法让它工作。

文档说将数据道具作为函数传递给画布,以便访问画布上下文以添加渐变。不幸的是,这是行不通的。

这是文件的代码和框:https://codesandbox.io/s/modest-bird-j2in8(文件 LineChartGradient.tsx)

我遇到的错误围绕着 Canvas 上下文并将数据函数传递给 chartjs 组件

数据

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"
        }
      ]
    };
  };

成分

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

错误#1

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

打字稿说这个对象可能是空的,这很好,我可以检查它是否存在,但这是我的第一个线索,即画布元素未被传递

错误 #2

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

类型 '(canvas: HTMLCanvasElement) => { labels: string[]; 中缺少属性 'datasets'数据集:

当将数据作为函数传递时,我会收到此错误,但是如果我只是将数据函数返回的对象放在数据道具内,则图形可以正常呈现(请参阅 LineChart.tsx)。

在 react-chartjs-2 中访问画布上下文以添加渐变填充的正确方法是什么?

【问题讨论】:

    标签: reactjs canvas chart.js react-chartjs-2


    【解决方案1】:

    这是因为您在调用它时没有将任何画布传递给数据函数

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

    但是这里也没有画布。如果您想制作自定义渐变,您需要为 backgroundColor 应用一个可编写脚本的选项,如下所示:

    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)"
        }]
      };
    };
    

    还要确保在您的数据字段中调用该函数,以便您的 html 变为:

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

    工作代码沙盒:https://codesandbox.io/s/interesting-faraday-204ugi?file=/src/LineChartGradient.tsx

    【讨论】:

      【解决方案2】:

      如果有人需要 React 解决方案,那么此处的解决方案可能会产生其他错误,例如“createLinearGradient 不是函数”或者“document.getElementById() 返回 null”因为它在 DOM 加载之前寻找图表 ID。缺少 React 的 ChartJS 文档也于事无补。

      一个干净的解决方案是将图表创建为功能组件,并确保注册所有需要的 ChartJS 资产。

      1. 确保 ChartJS 已正确初始化和注册

      import { Line } from 'react-chartjs-2' import { Chart as ChartJS, CategoryScale, LinearScale, PointElement, LineElement, Title, Tooltip, Legend, Filler, ScriptableContext } from "chart.js";
      
      ChartJS.register(CategoryScale,LinearScale,PointElement,LineElement,Title,Tooltip,Legend,Filler);
      

      2.使用ScriptableContext添加渐变

      backgroundColor: (context: ScriptableContext<"line">) => { const ctx = context.chart.ctx; const gradient = ctx.createLinearGradient(0, 0, 0, 200); gradient.addColorStop(0, "rgba(238,174,202,1)"); gradient.addColorStop(1, "rgba(238,174,202,0)"); return gradient; },
      

      带有折线图渐变的 Live Codepen enter link description here

      【讨论】:

        【解决方案3】:

        所以看起来你的代码有很多错误,我试图通过解决第二个问题来提供帮助,data 应该是 json 而不是函数所以要解决这个问题你应该在像这样传递之前执行函数:

        &lt;Line data={data()} options={options} /&gt;

          
          export default function Chart(){
            return (
            <div>
            {
            /****
            pass data() not data
            ****/
            }
              <Line data={data()} options={options} />
            </div>
          );
          }

        【讨论】:

        • 我之前试过这个不是吗,这也会立即触发数据函数,而不是将其作为道具传递,然后它应该从图表 js lib 传递上下文
        • 你试过在外面执行它并将它分配给一个变量然后传递它?
        • 这是不正确的。 Data 还接受一个重要的函数,该函数将 html canvas 元素作为第一个参数,从而使 OP 所询问的内容变得更加容易。