ChartJSNodeCanvas加载annotation插件报HTMLCanvasElement未定义错误
问题场景
- 需求:在服务端将Chart.js图表渲染生成为PNG文件,因图表X轴为时间类型,需要引入日期处理适配器
- 预期效果:加载
chartjs-plugin-annotation注解插件与chartjs-adapter-date-fns日期适配器后,正常渲染带注解的时间轴图表 - 实际表现:加载注解插件时抛出
HTMLCanvasElement is not defined错误;注释掉注解插件的modern模式加载配置后代码可正常运行,但图表注解无法显示;同一份图表配置在浏览器端运行时注解可正常展示
复现代码
初始化ChartJSNodeCanvas实例与渲染逻辑:
const chartJSNodeCanvas = new ChartJSNodeCanvas({ width: 512, height: 400, backgroundColour: "white", plugins: { modern: ['chartjs-plugin-annotation'], globalVariableLegacy: ["chartjs-adapter-date-fns"], }, }); const image = await chartJSNodeCanvas.renderToBuffer(config); fs.writeFileSync("c:/wswin/mychart.png", image);
报错信息
error: HTMLCanvasElement is not defined HTMLCanvasElement is not defined {"stack":"ReferenceError: HTMLCanvasElement is not defined\n at isImageOrCanvas (C:\\Users\\baumanng\\Documents\\Visual Studio Code\\wetterstation\\node_modules\\chartjs-plugin-annotation\\dist\\chartjs-plugin-annotation.js:334:57)\n....
当前依赖版本
"chartjs": "^0.3.24", "chartjs-adapter-date-fns": "^1.1.0-beta.1", "chartjs-node-canvas": "^4.1.6", "chartjs-plugin-annotation": "^1.3.1",
问题根因
- 依赖包安装错误:你安装的
chartjs是npm上已废弃的占位包,Chart.js的正确包名为chart.js,版本不匹配会直接导致插件加载链路异常。 - 插件加载模式配置错误:
chartjs-plugin-annotation内部做图片/画布类型校验时,会读取浏览器环境全局的HTMLCanvasElement构造函数做类型判断,Node环境默认不存在该全局对象;你将插件放在modern加载列表中时,chartjs-node-canvas不会为该插件提前模拟浏览器全局环境,直接触发引用错误。而浏览器环境自带HTMLCanvasElement全局对象,所以同一份配置在浏览器端可以正常运行。
解决步骤
- 第一步:修正依赖,卸载错误的chartjs包,安装版本匹配的正确依赖
执行以下命令:
该版本和你当前使用的npm uninstall chartjs npm install chart.js@3.9.1chartjs-node-canvas@4.1.6、chartjs-plugin-annotation@1.3.1、chartjs-adapter-date-fns@1.1.0-beta.1完全兼容。 - 第二步:调整插件注册方式,补全Node环境缺失的全局对象
放弃在ChartJSNodeCanvas配置项中自动加载插件的方式,改为手动注册插件,同时提前挂载全局HTMLCanvasElement构造函数,修改后的代码如下:const fs = require('fs'); const { ChartJSNodeCanvas } = require('chartjs-node-canvas'); const Chart = require('chart.js'); const annotationPlugin = require('chartjs-plugin-annotation'); // 加载时间适配器 require('chartjs-adapter-date-fns'); const { createCanvas } = require('canvas'); // 补全Node环境缺失的全局构造函数,解决annotation插件的类型校验报错 global.HTMLCanvasElement = createCanvas(1, 1).constructor; // 手动注册注解插件 Chart.register(annotationPlugin); // 初始化画布实例,无需再在plugins字段中重复加载已注册的插件 const chartJSNodeCanvas = new ChartJSNodeCanvas({ width: 512, height: 400, backgroundColour: "white" }); // 后续渲染逻辑保持不变 (async () => { const image = await chartJSNodeCanvas.renderToBuffer(config); fs.writeFileSync("c:/wswin/mychart.png", image); })(); - 第三步:重新运行代码即可正常生成带注解、时间轴的PNG图表,不会再触发
HTMLCanvasElement is not defined错误。
内容的提问来源于stack exchange,提问作者GeorgB
相关产品推荐
相关产品推荐

