如何冻结Highchart动画 实现Ajax刷新时样条曲线就地更新不重绘
问题根源
你当前代码每次Ajax请求成功后都会调用Highcharts.chart()方法重新创建完整的图表实例,本质是把旧图表销毁后重新渲染整个画布,这和是否关闭animation参数无关,所以就算关了动画也会出现全量重绘的问题。
解决方法
核心逻辑是仅初始化一次图表实例,后续复用实例做增量数据更新,不需要每次都重新构建整个图表配置。Highcharts提供了专门的API用来更新坐标轴、系列数据,调用这些接口只会更新变化的部分,不会触发全量重绘。
修正后的代码
$(document).ready(function(){ // 把chart实例放到外层作用域,全局复用 let chart = null; function init_chart(response) { // 仅第一次调用时初始化图表,之后不再走这个逻辑 chart = Highcharts.chart('data-container', { chart: { renderTo: 'data-container', defaultSeriesType: 'spline' }, title: { text: 'Live Reddit Stream' }, xAxis: { categories: response.halfhour }, yAxis: { minPadding: 0.2, maxPadding: 0.2, title: { text: 'Value', margin: 80 } }, series: [{ name: 'reddit_stream', data: response.count }] }); } function update_chart(response) { // 直接调用API增量更新,不会全量重绘 chart.xAxis[0].setCategories(response.halfhour, false); // 第二个参数false表示先不重绘,等数据更新完一起重绘 chart.series[0].setData(response.count, true); // 第二个参数true表示更新完数据后触发重绘 } $(function fetchdata() { $.ajax({ url: '/fetch_data', type:'POST', dataType: 'json', // 建议明确指定dataType为json,避免解析出错 success: function(output_string){ if(chart === null) { // 第一次拿到数据初始化图表 init_chart(output_string); } else { // 后续直接更新数据 update_chart(output_string); } }, complete:function(){ setTimeout(fetchdata,10000); }, error: function (xhr, ajaxOptions, thrownError){ console.log(xhr.statusText); console.log(thrownError); } }); }); });
关键改动说明
- 全局复用同一个chart实例,避免重复创建销毁图表
- 第一次拿到数据才初始化图表,避免空数据渲染异常
- 用
setCategories()更新x轴分类,setData()更新系列数据,两个方法配合仅做增量更新,不会触发全量重绘 - 调整了更新时的重绘时机,先更新坐标轴再更新数据,只触发一次重绘,性能更好
如果想要保留更新时的平滑过渡效果,不需要关闭animation参数,Highcharts会自动给数据变化添加过渡动画,效果比全量重绘自然很多。
内容的提问来源于stack exchange,提问作者ashkrelja
相关产品推荐
相关产品推荐

