You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Chart.js v4.4.0在Angular中设置图例左右位置触发运行时错误

Angular中Chart.js v4.4.0饼图图例设为left/right触发options为null的运行时错误解决方法

问题现象

在Angular项目中使用Chart.js v4.4.0创建饼图时,将图例位置从top或bottom修改为left或right,会触发运行时错误。错误出现在Chart.js内部的inRange函数中,提示无法读取null的spacing属性,即this.options为null。

错误代码片段

触发错误的Chart.js内部函数:

inRange(chartX, chartY, useFinalPosition) {
    const point = this.getProps([
        'x',
        'y'
    ], useFinalPosition);
    const { angle , distance  } = getAngleFromPoint(point, {
        x: chartX,
        y: chartY
    });
    const { startAngle , endAngle , innerRadius , outerRadius , circumference  } = this.getProps([
        'startAngle',
        'endAngle',
        'innerRadius',
        'outerRadius',
        'circumference'
    ], useFinalPosition);
    const rAdjust = this.options.spacing / 2; // 此处this.options为null,触发错误
    const _circumference = valueOrDefault(circumference, endAngle - startAngle);
    const betweenAngles = _circumference >= TAU || _angleBetween(angle, startAngle, endAngle);
    const withinRadius = _isBetween(distance, innerRadius + rAdjust, outerRadius + rAdjust);
    return betweenAngles && withinRadius;
}

问题原因

这是Chart.js v4.4.0的已知bug:当饼图的图例设置为垂直方向(left/right)时,图例项的交互逻辑会错误地访问未初始化的options对象;而水平方向(top/bottom)的图例不会触发该问题。该bug已在后续版本(v4.4.1及以上)中修复。

解决方案

方案1:升级Chart.js版本

直接将Chart.js升级到修复该bug的版本,执行以下命令:

npm install chart.js@4.4.1 --save
# 或者升级到最新稳定版
npm install chart.js@latest --save

升级后无需修改原有组件代码,图例设置为left/right即可正常运行。

方案2:临时禁用图例交互

如果不需要图例的点击交互功能,可以在图例配置中添加interactive: false,避免触发错误逻辑:
修改组件中Chart的options配置:

options: {
  responsive: true,
  plugins: {
    legend: {
      display: true,
      position: 'right',
      interactive: false // 禁用图例交互
    },
    title: {
      display: true,
      text: 'Chart.js Pie Chart',
    },
  },
}

方案3:手动补全图例项的options(临时兼容)

如果暂时无法升级版本,可以在Chart初始化完成后,手动为图例项补充默认的options:
修改组件的_initChart函数,在创建chart后添加以下代码:

private _initChart() {
  const ctx = this._chartPie.nativeElement.getContext('2d');
  this.zone.runOutsideAngular(() => {
    this.chart = new Chart(ctx, {
      // 原有配置...
    });

    // 手动补全图例项的options
    if (this.chart?.plugins) {
      const legendPlugin = this.chart.plugins.find(p => p.id === 'legend');
      if (legendPlugin?.legend?.items) {
        legendPlugin.legend.items.forEach(item => {
          if (!item.options) {
            item.options = { spacing: 0 };
          }
        });
      }
    }
  });
}

原组件代码

@ViewChild('chartPie') private _chartPie: ElementRef<HTMLCanvasElement>;

public chart: Chart<'pie'>;

public pieChartData = [
  { year: 2010, count: 10 },
  { year: 2011, count: 20 },
  { year: 2012, count: 45 },
];

constructor(private zone: NgZone) {}

ngOnInit(): void {
  Chart.register(...registerables);
}

public ngAfterViewInit(): void {
  this._initChart();
}

public ngOnDestroy(): void {
  if (this.chart) this.chart.destroy();
}

private _initChart() {
  const ctx = this._chartPie.nativeElement.getContext('2d');
  this.zone.runOutsideAngular(() => {
    this.chart = new Chart(ctx, {
      type: 'pie',
      data: {
        labels: this.pieChartData.map((d) => d.year),
        datasets: [
          {
            label: 'Acquisitions by year',
            data: this.pieChartData.map((d) => d.count),
          },
        ],
      },
      options: {
        responsive: true,
        plugins: {
          legend: {
            display: true,
            position: 'right', // "top/bottom" works fine
          },
          title: {
            display: true,
            text: 'Chart.js Pie Chart',
          },
        },
      },
    });
  });

  // this.chart.update();
}

内容的提问来源于stack exchange,提问作者Ravi Anand

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.05 10:02:07