如何在draw()函数中实现Chart.js销毁以更新环形图?
问题
我有一个环形图(doughnut Chart),希望每次在下拉菜单选择不同选项时,用新的数据集stats更新图表。但代码写在draw()函数里,导致图表重复绘制,一直收到错误提示:
Canvas is already in use. Chart with ID '0' must be destroyed before the canvas with ID 'myChart' can be reused.
相关代码如下:
var config = { type: 'doughnut', data: { labels: legend, datasets: [{ backgroundColor: ['rgb(204,0,0)', 'rgb(241,194,50)', 'rgb(41,134,204)', 'rgb(106,168,79)', 'rgb(255,62,153)'], data: stats, }] }, plugins: [hoverLabel], options: { radius: this.radius, hoverOffset: 30, responsive: true, maintainAspectRatio: false, plugins: { title: { display: true, text: "Top 5 causes of death in " + country, color: 'rgb(0,0,0)', align: 'center', padding: 15, font: { size: 25 } }, legend: { position: 'right', title: { display: true, color: 'rgb(0,0,0)', text: 'Legend', font: { weight: 'bold', size: 20 }, }, labels: { color: 'rgb(0,0,0)', usePointStyle: true, padding: 15, font: { size: 15, weight: 'bold' } } } } } }; let mychart = new Chart('myChart', config);

解决方案
核心问题是每次调用draw()都会创建新的Chart实例,但Canvas已被旧实例占用。推荐两种解决方式:
方式1:复用实例更新数据(性能更优)
把图表实例变量提升到draw()函数外的作用域,避免每次调用重新声明,后续直接更新实例数据并渲染:
// 将实例变量放在全局/外部作用域,保留引用 let mychart = null; function draw() { var config = { type: 'doughnut', data: { labels: legend, datasets: [{ backgroundColor: ['rgb(204,0,0)', 'rgb(241,194,50)', 'rgb(41,134,204)', 'rgb(106,168,79)', 'rgb(255,62,153)'], data: stats, }] }, plugins: [hoverLabel], options: { radius: this.radius, hoverOffset: 30, responsive: true, maintainAspectRatio: false, plugins: { title: { display: true, text: "Top 5 causes of death in " + country, color: 'rgb(0,0,0)', align: 'center', padding: 15, font: { size: 25 } }, legend: { position: 'right', title: { display: true, color: 'rgb(0,0,0)', text: 'Legend', font: { weight: 'bold', size: 20 }, }, labels: { color: 'rgb(0,0,0)', usePointStyle: true, padding: 15, font: { size: 15, weight: 'bold' } } } } } }; if (mychart) { // 更新核心数据 mychart.data.labels = legend; mychart.data.datasets[0].data = stats; // 更新标题文本 mychart.options.plugins.title.text = "Top 5 causes of death in " + country; // 重新渲染图表 mychart.update(); } else { // 首次创建图表实例 mychart = new Chart('myChart', config); } }
方式2:销毁旧实例后重建
如果不需要复用实例,每次创建新图表前先销毁旧实例:
let mychart = null; function draw() { // 存在旧实例则销毁 if (mychart) { mychart.destroy(); } var config = { // 原config内容不变 }; // 创建新的图表实例 mychart = new Chart('myChart', config); }
注意点
- 优先用方式1,销毁重建会带来额外性能开销;
- 确保
legend、stats、country在draw()调用时已更新为最新值; - 若需修改其他配置(比如颜色、图例位置),可直接修改实例属性后调用
update()。
内容的提问来源于stack exchange,提问作者wubberlublub
相关产品推荐
相关产品推荐

