Chart.js v3.9.1如何实现环形图数据的定时更新?
解决Chart.js v3.9.1环形图无法定时更新数据的问题
问题场景
用Chart.js v3.9.1开发了一个从API获取数据的环形图,图表能正常显示,但没法实现每2秒自动更新数据。原代码如下:
原Chart.js代码
const totalRunTime = current_array.MTConnectStreams.Streams.DeviceStream.ComponentStream[12].Samples.DynamicBasicData[1]; const totalTimeRemaining = current_array.MTConnectStreams.Streams.DeviceStream.ComponentStream[12].Samples.DynamicBasicData[13]; const timeRemaining = ((totalTimeRemaining / totalRunTime) * 100) // Setup const datapoints = [(100 - timeRemaining), timeRemaining]; const data = { datasets: [{ data: datapoints, backgroundColor: ['rgba(20, 121, 255, 0.7)', 'rgba(208, 208, 208, 0.5)'], borderWidth: 1, cutout: '70%' }] }; // Counter const counter = { id: 'counter', beforeDraw( chart, args, options ) { const { ctx, chartArea: { top, right, bottom, left, width, height } } = chart; ctx.save(); ctx.font = options.fontSize + 'px ' + options.fontFamily; ctx.textAlign = 'center'; ctx.fillStyle = options.fontColor; ctx.fillText(datapoints[0].toFixed(3) + '%', width / 2, (height / 2) + (options.fontSize * 0.34)); } }; // Config const config = { type: 'doughnut', data, options: { plugins: { legend: { display: false }, tooltip: { enabled: false }, counter: { fontColor: '#193b68', fontSize: '16', fontFamily: 'Sofia Pro Medium' } } }, plugins: [counter] }; // Render init const doughnutChart = new Chart( document.getElementById('doughnutChart'), config ); setInterval(function addData(chart, data) { chart.data.datasets.forEach((dataset) => { dataset.data = data; }); chart.update('none'); }, 2000 );
原HTML代码
<canvas id="doughnutChart"></canvas>
问题原因
- 数据未重新获取:初始化时只取了一次
current_array的数据,定时器里没有重新请求API或更新current_array,导致始终用初始值更新 - 定时器参数错误:
setInterval里的addData函数需要传入chart和data,但实际执行时没传参,data为undefined,无法更新图表 - 插件数据未同步:自定义
counter插件直接用初始化时的datapoints变量,没从当前图表实例取最新数据,导致中心百分比不更新
修复后的完整代码
修复后的Chart.js代码
// 封装获取最新数据的函数 function getLatestData() { // 若current_array来自API,需在此处补充API请求逻辑,确保拿到最新数据 const totalRunTime = current_array.MTConnectStreams.Streams.DeviceStream.ComponentStream[12].Samples.DynamicBasicData[1]; const totalTimeRemaining = current_array.MTConnectStreams.Streams.DeviceStream.ComponentStream[12].Samples.DynamicBasicData[13]; const timeRemaining = ((totalTimeRemaining / totalRunTime) * 100); return [(100 - timeRemaining), timeRemaining]; } // Counter插件:从图表实例中获取最新数据 const counter = { id: 'counter', beforeDraw(chart, args, options) { const { ctx, chartArea: { width, height } } = chart; ctx.save(); ctx.font = `${options.fontSize}px ${options.fontFamily}`; ctx.textAlign = 'center'; ctx.fillStyle = options.fontColor; // 从当前图表数据中取最新值 const latestValue = chart.data.datasets[0].data[0]; ctx.fillText(`${latestValue.toFixed(3)}%`, width / 2, (height / 2) + (options.fontSize * 0.34)); ctx.restore(); // 恢复上下文,避免影响其他绘制 } }; // Config const config = { type: 'doughnut', data: { datasets: [{ data: getLatestData(), // 初始化时调用一次获取数据 backgroundColor: ['rgba(20, 121, 255, 0.7)', 'rgba(208, 208, 208, 0.5)'], borderWidth: 1, cutout: '70%' }] }, options: { plugins: { legend: { display: false }, tooltip: { enabled: false }, counter: { fontColor: '#193b68', fontSize: '16', fontFamily: 'Sofia Pro Medium' } } }, plugins: [counter] }; // 初始化图表 const doughnutChart = new Chart( document.getElementById('doughnutChart'), config ); // 定时更新图表 setInterval(() => { const newData = getLatestData(); // 更新图表数据 doughnutChart.data.datasets[0].data = newData; // 触发图表更新,'none'表示无动画 doughnutChart.update('none'); }, 2000);
修复后的HTML代码(不变)
<canvas id="doughnutChart"></canvas>
关键修复说明
- 封装数据获取函数:把数据计算逻辑放到
getLatestData里,每次定时器触发时调用,确保拿到最新数据(如果是API数据源,需在函数内补充请求逻辑更新current_array) - 修正定时器逻辑:直接在定时器回调里获取新数据,赋值给图表的
dataset.data后调用update方法完成更新 - 插件同步数据:插件内部从
chart.data.datasets[0].data取最新值,不再依赖外部变量,保证中心百分比和图表数据同步
内容的提问来源于stack exchange,提问作者Empire Hive
相关产品推荐
相关产品推荐

