简体   繁体   中英

Canvas: "object is undefined"

I'm trying to create a line in Canvas. Everything was going well until I got stuck on this part:

import { Doughnut } from "react-chartjs-2";
import "chart.js/auto";
import { Chart, ChartData, ChartDataset, ChartOptions } from "chart.js";

function DoughnutChart(){
  const doughnutLabelsLine = {
    id: "doughnutLabelsLine",
    afterDraw(chart: Chart<"doughnut">, args: any, options: ChartOptions) {
      const {
        ctx,
        chartArea: { top, bottom, left, right, width, height },
      } = chart;

      chart.data.datasets.forEach((dataset, i) => {
        // console.log(chart.getDatasetMeta(i));
        chart.getDatasetMeta(i).data.forEach((datapoint, index) => {
          console.log(dataset);
          const { x, y } = datapoint.tooltipPosition();
          //Object is possibly undefined
          ctx.fillStyle = dataset?.borderColor[index];
          ctx.fillRect(x, y, 2, 2);
        });
      });
    },
  };

//config...
//dataDoughnut

return (
        <div className="col-span-6">
          <Doughnut
            data={dataDoughnut}
            options={config}
            width={200}
            height={300}
            plugins={[doughnutLabelsLine]}
          />
        </div>
);
}
export default DoughnutChart;

I have tried putting it into an if statement as well and using an exclamation mark, but that didn't work. Am I missing something here?

Edit: Made an adjustment based on user2057925's suggestion

DoughnutLabelsLine

  const doughnutLabelsLine = {
    id: "doughnutLabelsLine",
    afterDraw(chart: Chart<"doughnut">, args: any, options: ChartOptions) {
      const {
        ctx,
        chartArea: { top, bottom, left, right, width, height },
      } = chart;

      chart.data.datasets.forEach((dataset, i) => {
        // console.log(chart.getDatasetMeta(i));
        chart.getDatasetMeta(i).data.forEach((datapoint, index) => {
          console.log(dataset);
          const { x, y } = datapoint.tooltipPosition();
          ctx.save();
          const borderColor = datapoint.options.borderColor as
            | string
            | CanvasGradient
            | CanvasPattern;
          ctx.fillStyle = borderColor;
          // ctx.fillStyle = dataset?.borderColor[index];
          ctx.fillRect(x, y, 10, 10);
          ctx.restore();
        });
      });
    },
  };

I think the undefined error is not related to the dataset instance but due to the borderColor one.

Anyway the best thing could be to use the datapoint.options.borderColor because:

  1. you shouldn't need either the dataset instance or the index
  2. the datapoint, being an ArcElement , provides in options node all its options, even if they are configured (using default).

 const p = { id: "doughnutLabelsLine", afterDraw(chart, args, options) { chart.data.datasets.forEach((dataset, i) => { chart.getDatasetMeta(i).data.forEach((datapoint, index) => { const { x, y } = datapoint.tooltipPosition(); ctx.save(); ctx.fillStyle = datapoint.options.borderColor; ctx.fillRect(x -5, y - 5, 10, 10); ctx.restore(); }); }); } }; const config = { type: 'doughnut', plugins: [p], data: { labels: [6, 6, 4, 3, 2, 2, 1], datasets: [{ label: 'Simple treemap', data: [6, 6, 4, 3, 2, 2, 1], borderColor: ['red', 'blue'] }] }, }; const ctx = document.getElementById('myChart').getContext('2d'); new Chart(ctx, config);
 .myChartDiv { max-width: 600px; max-height: 400px; }
 <html> <head> <script src="https://cdn.jsdelivr.net/npm/chart.js@3.9.1/dist/chart.min.js"></script> </head> <body> <div class="myChartDiv"> <canvas id="myChart" width="600" height="400"/> </div> </body> </html>

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM