Chart.js批量生成折线图图片时onComplete回调数据异常问题排查
问题原因及解决方案
核心错误原因
- 全局资源复用导致内容被覆盖
你将<canvas>元素实例chart_cp、Image实例imgur都定义为全局变量,每次调用create_trend_vsr生成图表时,都是在同一个canvas上渲染,后续生成的图表会直接覆盖之前的内容。等到异步的onComplete回调触发时,canvas上已经只剩最后一次渲染的图表,所以导出的base64全部相同。 - 异步闭包引用了最后一次的参数值
onComplete是Chart.js动画完成后才触发的异步回调,你直接在回调中引用函数入参messstelle、date等变量,等回调执行时,所有同步的图表生成逻辑已经执行完毕,回调捕获的变量都是最后一次调用函数时传入的值,所以打印的永远是最后一份数据。 - 回调内修改canvas尺寸的错误操作
你在onComplete回调中重新给chart_cp.width、chart_cp.height赋值,这个操作会直接清空canvas当前的所有绘制内容,也会导致导出的内容异常。
修复方案
- 取消全局的canvas、Image实例复用,每次生成图表都创建独立的实例:
// 仅保留需要全局访问的变量定义 var width=400; var height=150; var imageliste = []; function create_trend_vsr(messstelle, date, ergeb, akl, wl, width, height){ var imagedataurltemp; // 每次生成图表创建独立的canvas实例 const chart_cp = document.createElement("canvas"); chart_cp.width = width; chart_cp.height = height; const chart_ctxp = chart_cp.getContext("2d"); // 每次创建独立的Image实例 const imgur = new Image(); // 原有参数打印逻辑不变 console.log("Messstelle"); console.log(messstelle); console.log("Datum"); console.log(date); console.log("Ergebnis"); console.log(ergeb); console.log("AKL"); console.log(akl); console.log("WL"); console.log(wl); var LineChart = new Chart(chart_cp, { type: 'line', data: { labels: date, datasets: [{ label: 'AKL', data: akl, borderColor: 'red', borderWidth: 3, lineTension: 0, pointRadius:0, fill: false },{ label: 'WL', data: wl, borderColor: 'blue', borderWidth: 3, lineTension: 0, pointRadius:0, fill: false },{ label: 'Analysis', data: ergeb, borderColor: 'green', borderWidth: 1, lineTension: 0, pointRadius:2, }] }, options: { animation: { onComplete: function() { // 删除修改canvas宽高的逻辑,初始化时已经设置完成 imagedataurltemp= chart_cp.toDataURL("image/png"); imgur.src=LineChart.toBase64Image(); imageliste.push(imgur.src); console.log("Messstelle"); console.log(messstelle); console.log("Datum"); console.log(date); console.log("Ergebnis"); console.log(ergeb); console.log("AKL"); console.log(akl); console.log("WL"); console.log(wl); console.log(imageliste.length); console.log(imgur.src); } } } }); }
- 如果需要批量生成多个图表,建议用
async/await控制生成顺序,等前一个图表导出完成后再生成下一个,避免出现时序问题。
内容的提问来源于stack exchange,提问作者Thomas Zlabinger
相关产品推荐
相关产品推荐

