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

Angular/Ionic项目Firefox下ng2-charts报NS_ERROR_FAILURE错误求助

Angular/Ionic项目中Firefox下ng2-charts+Chart.js的NS_ERROR_FAILURE错误解决思路

问题描述

在Angular/Ionic项目中,仅Firefox浏览器使用ng2-charts和Chart.js时会抛出0x80004005(NS_ERROR_FAILURE)错误,触发点在computeLabelSizes方法,导致应用崩溃,但Chrome和Edge运行正常。

错误栈信息

ERROR Error: Uncaught (in promise): [Exception... "Failure"  nsresult: "0x80004005 (NS_ERROR_FAILURE)"  location: "JS frame :: http://localhost:4200/default-src_app_explore-container_explore-container_module_ts.js :: computeLabelSizes :: line 11070"  data: no]
computeLabelSizes@http://localhost:4200/default-src_app_explore-container_explore-container_module_ts.js:11070:7
_getLabelSizes@http://localhost:4200/default-src_app_explore-container_explore-container_module_ts.js:11730:39
fit@http://localhost:4200/default-src_app_explore-container_explore-container_module_ts.js:11593:29
update@http://localhost:4200/default-src_app_explore-container_explore-container_module_ts.js:11405:10
fitBoxes@http://localhost:4200/default-src_app_explore-container_explore-container_module_ts.js:7044:11
update@http://localhost:4200/default-src_app_explore-container_explore-container_module_ts.js:7254:15
updateLayout@http://localhost:4200/default-src_app_explore-container_explore-container_module_ts.js:9503:20
update@http://localhost:4200/default-src_app_explore-container_explore-container_module_ts.js:9460:10
construct@http://localhost:4200/default-src_app_explore-container_explore-container_module_ts.js:9194:10
Chart@http://localhost:4200/default-src_app_explore-container_explore-container_module_ts.js:9133:10
getChartBuilder@http://localhost:4200/default-src_app_explore-container_explore-container_module_ts.js:35766:12
refresh@http://localhost:4200/default-src_app_explore-container_explore-container_module_ts.js:35975:25
ngOnInit@http://localhost:4200/default-src_app_explore-container_explore-container_module_ts.js:35307:10
callHook@http://localhost:4200/vendor.js:69461:14
callHooks@http://localhost:4200/vendor.js:69417:17
executeInitAndCheckHooks@http://localhost:4200/vendor.js:69353:14
refreshView@http://localhost:4200/vendor.js:80656:35
refreshComponent@http://localhost:4200/vendor.js:81937:18
refreshChildComponents@http://localhost:4200/vendor.js:80369:21
refreshView@http://localhost:4200/vendor.js:80706:29
refreshComponent@http://localhost:4200/vendor.js:81937:18
refreshChildComponents@http://localhost:4200/vendor.js:80369:21
refreshView@http://localhost:4200/vendor.js:80706:29
detectChangesInternal@http://localhost:4200/vendor.js:82097:16
detectChanges@http://localhost:4200/vendor.js:82689:26
setActive@http://localhost:4200/vendor.js:6023:42
activateWith@http://localhost:4200/vendor.js:7170:20
activateRoutes@http://localhost:4200/vendor.js:117943:28
activateChildRoutes/<@http://localhost:4200/vendor.js:117887:12
activateChildRoutes@http://localhost:4200/vendor.js:117886:25
activateRoutes@http://localhost:4200/vendor.js:117950:14
activateChildRoutes/<@http://localhost:4200/vendor.js:117887:12
activateChildRoutes@http://localhost:4200/vendor.js:117886:25
activateRoutes@http://localhost:4200/vendor.js:117946:16
activateChildRoutes/<@http://localhost:4200/vendor.js:117887:12
activateChildRoutes@http://localhost:4200/vendor.js:117886:25
activateRoutes@http://localhost:4200/vendor.js:117950:14
activateChildRoutes/<@http://localhost:4200/vendor.js:117887:12
activateChildRoutes@http://localhost:4200/vendor.js:117886:25
activate@http://localhost:4200/vendor.js:117787:10
activateRoutes/<@http://localhost:4200/vendor.js:117770:99
_next@http://localhost:4200/vendor.js:25460:29
next@http://localhost:4200/vendor.js:23721:12
_next@http://localhost:4200/vendor.js:26324:22
next@http://localhost:4200/vendor.js:23721:12
_next@http://localhost:4200/vendor.js:25466:22
next@http://localhost:4200/vendor.js:23721:12
notifyNext@http://localhost:4200/vendor.js:26033:22
_next@http://localhost:4200/vendor.js:24179:17
next@http://localhost:4200/vendor.js:23721:12
_next@http://localhost:4200/vendor.js:25466:22
next@http://localhost:4200/vendor.js:23721:12
subscribeToArray/<@http://localhost:4200/vendor.js:27123:16
_trySubscribe@http://localhost:4200/vendor.js:23252:19
subscribe@http://localhost:4200/vendor.js:23234:172
call@http://localhost:4200/vendor.js:25443:19
subscribe@http://localhost:4200/vendor.js:23232:25
innerSubscribe@http://localhost:4200/vendor.js:24250:19
_innerSub@http://localhost:4200/vendor.js:26001:93
_next@http://localhost:4200/vendor.js:25988:10
next@http://localhost:4200/vendor.js:23721:12
notifyNext@http://localhost:4200/vendor.js:26033:22
_next@http://localhost:4200/vendor.js:24179:17
next@http://localhost:4200/vendor.js:23721:12
_next@http://localhost:4200/vendor.js:25466:22
next@http://localhost:4200/vendor.js:23721:12
_next@http://localhost:4200/vendor.js:26094:24
next@http://localhost:4200/vendor.js:23721:12
_complete@http://localhost:4200/vendor.js:25164:24
complete@http://localhost:4200/vendor.js:23737:12
_complete@http://localhost:4200/vendor.js:24547:24
complete@http://localhost:4200/vendor.js:23737:12
subscribeToArray/<@http://localhost:4200/vendor.js:27126:14
_trySubscribe@http://localhost:4200/vendor.js:23252:19
subscribe@http://localhost:4200/vendor.js:23234:172
call@http://localhost:4200/vendor.js:24524:19
subscribe@http://localhost:4200/vendor.js:23232:25
call@http://localhost:4200/vendor.js:25145:19
subscribe@http://localhost:4200/vendor.js:23232:25
call@http://localhost:4200/vendor.js:26077:19
subscribe@http://localhost:4200/vendor.js:23232:25
call@http://localhost:4200/vendor.js:25443:19
subscribe@http://localhost:4200/vendor.js:23232:25
innerSubscribe@http://localhost:4200/vendor.js:24250:19
_innerSub@http://localhost:4200/vendor.js:26001:93
_next@http://localhost:4200/vendor.js:25988:10
next@http://localhost:4200/vendor.js:23721:12
notifyNext@http://localhost:4200/vendor.js:26033:22
_next@http://localhost:4200/vendor.js:24179:17
next@http://localhost:4200/vendor.js:23721:12
_next@http://localhost:4200/vendor.js:25466:22
next@http://localhost:4200/vendor.js:23721:12
_next@http://localhost:4200/vendor.js:26324:22
next@http://localhost:4200/vendor.js:23721:12
notifyNext@http://localhost:4200/vendor.js:26033:22
_next@http://localhost:4200/vendor.js:24179:17

报错代码行

报错代码行

复现说明

因ng2-charts起始模板无法正常运行(控制台报404错误),无法提供在线演示,可通过以下步骤复现:创建新的Angular/Ionic项目,安装指定版本依赖,使用如下代码:

项目依赖版本

(注:项目为线上运行状态,无法大幅升级)

{
  "@angular/core": "^14.0.0",
  "@ionic/angular": "^6.1.9",
  "chart.js": "^2.9.4",
  "ng2-charts": "^2.4.2"
}

触发条件

  • 错误仅在Firefox中出现,导致应用崩溃;Chrome和Edge运行正常
  • 将scaleLabel和ticks的display设为false后,错误消失
  • 即使关闭上述选项,开启[legend]="true"时错误会再次出现

HTML代码

<div id="container">
  <div>
    <canvas
      baseChart
      width="300"
      height="300"
      [datasets]="previewChartData"
      [options]="previewChartOptions"
      [legend]="false"
      [chartType]="'line'"
    ></canvas>
  </div>
</div>

TS代码

public previewChartData = [
    {
      data: [
        {
          title: 'Title',
          x: 10,
          y: 20
        }
      ]
    }
  ];
  public previewChartOptions = {
    scales: {
      xAxes: [
        {
          type: 'linear',
          scaleLabel: {
            display: true,
            labelString: 'asd'
          },
          ticks: {
            display: true
          }
        }
      ],
      yAxes: [
        {
          type: 'linear',
          scaleLabel: {
            display: true,
            labelString: 'qwe'
          },
          ticks: {
            display: true
          }
        }
      ]
    }
  };

已尝试的解决方法

  • 更新ng2-charts和chart.js的小版本
  • 将图表移出ngIf指令
  • 调整ViewChild的static属性或移除ViewChild
  • 删除node_modules后重新安装
  • 在项目其他图表上测试相同配置,错误依旧
  • 调整图表宽高、父容器样式
  • 调整responsive和maintainAspectRatio选项
  • 修改报错处的chart.js代码

待尝试的有效解决方法

1. 强制指定图表字体配置

Firefox在Canvas文本渲染上和Chrome有差异,显式设置字体参数避免渲染异常:

public previewChartOptions = {
  defaultFontFamily: "'Arial', sans-serif",
  defaultFontSize: 12,
  defaultFontColor: '#666',
  scales: {
    // 原有配置...
  }
};

2. 延迟图表初始化

确保DOM完全渲染后再初始化图表,改用ngAfterViewInit生命周期钩子并添加短暂延迟:

import { Component, AfterViewInit, ViewChild } from '@angular/core';
import { BaseChartDirective } from 'ng2-charts';

export class YourComponent implements AfterViewInit {
  @ViewChild(BaseChartDirective) chart?: BaseChartDirective;

  ngAfterViewInit(): void {
    setTimeout(() => {
      this.chart?.refresh();
    }, 100);
  }
}

3. 修复Chart.js文本测量逻辑

针对Firefox的NS_ERROR_FAILURE错误,修改computeLabelSizes方法的文本测量逻辑,避免触发异常API:
找到Chart.js中该方法,替换文本测量部分:

function computeLabelSizes() {
  // 保留原有变量定义逻辑
  const textMetrics = ctx.measureText(label);
  return {
    width: textMetrics.width,
    height: parseInt(ctx.font.split(' ')[0], 10) || 12
  };
}

若无法直接修改node_modules,可使用patch-package工具生成补丁持久化修改。

4. 禁用Firefox硬件加速

通过CSS或JS禁用Canvas硬件加速,避免渲染冲突:

#container canvas {
  -moz-osx-font-smoothing: grayscale;
}

或:

ngAfterViewInit(): void {
  const canvas = document.querySelector('canvas[baseChart]') as HTMLCanvasElement;
  const ctx = canvas?.getContext('2d');
  if (ctx) {
    (ctx as any).mozImageSmoothingEnabled = false;
  }
}

5. 调整数据格式

将对象格式的点数据换成数组格式,触发Chart.js不同的渲染分支:

public previewChartData = [
    {
      data: [20],
      xAxisID: 'x-axis-0'
    }
  ];
public previewChartOptions = {
  scales: {
    xAxes: [
      {
        type: 'linear',
        scaleLabel: {
          display: true,
          labelString: 'asd'
        },
        ticks: {
          display: true,
          min: 0,
          max: 20,
          stepSize: 5
        }
      }
    ],
    // 原有y轴配置...
  }
};

6. 替换为CDN版本的Chart.js

引入CDN版本的Chart.js(对应2.9.4),替换本地npm包,避免打包兼容性问题:
在index.html中添加:

<script src="https://cdn.jsdelivr.net/npm/chart.js@2.9.4/dist/Chart.min.js"></script>

同时在angular.json中移除Chart.js的打包配置,确保使用全局Chart对象。

内容的提问来源于stack exchange,提问作者Taha Erden

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.13 23:35:21