ZingChart绘制20万+数据致页面卡顿,求优化方案
ZingChart大数量数据渲染卡顿问题解决方案
问题根源排查
- 冗余数据渲染:20万+数据点远超过屏幕像素上限(比如1920px屏幕最多显示1920个可见点),大量重叠点会导致不必要的绘制计算,这是卡顿核心原因。
- 频繁DOM操作:每次绘制都移除并重新创建图表容器,触发浏览器重排重绘,加重性能负担。
- 高消耗功能启用:
preview.live: true实时预览会持续监听交互并更新预览区域,额外占用CPU/GPU资源。 - 未启用高性能渲染:默认渲染模式对大数据量的适配不足,未利用GPU加速。
具体优化方案
1. 数据降采样(最核心优化)
通过降采样保留数据趋势的同时,将数据量压缩到屏幕可承载的范围(比如1000-2000个点),完全不影响视觉效果。
// 简单抽稀算法:按目标数量均匀采样,保留首尾点 function downsampleData(data, targetCount) { if (data.length <= targetCount) return data; const step = Math.floor(data.length / targetCount); const sampled = []; for (let i = 0; i < data.length; i += step) { sampled.push(data[i]); } // 确保最后一个数据点被保留,避免截断趋势 if (sampled[sampled.length - 1] !== data[data.length - 1]) { sampled.push(data[data.length - 1]); } return sampled; } // 在绘制函数中调用采样 function drawTimeVSAngleChart(containerId, timeArray, cpuArray, memoryArray){ // 目标采样数量,根据屏幕宽度调整(比如1920px屏幕设为1920) const targetPoints = 1000; const sampledTime = downsampleData(timeArray, targetPoints); const sampledCpu = downsampleData(cpuArray, targetPoints); const sampledMemory = downsampleData(memoryArray, targetPoints); // 后续配置使用采样后的数组 var configTimeAndAngle = { "scale-x": { zooming: true, labels: sampledTime, // 替换为采样后的时间数组 'max-items':8, 'min-items':7, item: { 'font-size':10 } }, "series": [{ "values": sampledCpu, // 替换为采样后的CPU数组 'line-color': "#3366ff", 'background-color': "#3366ff", text: "CPU Array" },{ "values": sampledMemory, // 替换为采样后的内存数组 'line-color': "#00cc99", 'background-color': "#00cc99", text: "Memory Array" }] // ... 其他原有配置 }; // ... 渲染代码 }
2. 启用高性能渲染模式
开启WebGL渲染利用GPU加速,关闭不必要的动画减少计算开销:
// 图表配置中添加高性能相关设置 var configTimeAndAngle = { "type": "line", plot: { animation: false, // 关闭绘制动画,大数据场景下无意义 line-width: 1 // 减小线宽,降低绘制计算量 }, // ... 其他原有配置 }; // 渲染时指定WebGL输出 zingchart.render({ id: containerId, data: configTimeAndAngle, height: "100%", width: "100%", output: 'webgl' // 优先WebGL,不支持则自动回退到Canvas });
3. 优化DOM操作
提前创建所有图表容器,避免频繁移除/添加DOM元素:
<!-- 提前在HTML中定义4个图表容器 --> <div id="canvas_div"> <div id="chart1" style="min-height: 400px; height: 500px; max-width: 100%;"></div> <div id="chart2" style="min-height: 400px; height: 500px; max-width: 100%;"></div> <div id="chart3" style="min-height: 400px; height: 500px; max-width: 100%;"></div> <div id="chart4" style="min-height: 400px; height: 500px; max-width: 100%;"></div> </div>
// 修改绘制函数,直接复用已有容器 function drawTimeVSAngleChart(containerId, timeArray, cpuArray, memoryArray){ // 移除原有的$('#lineChart').remove()和append代码 // ... 数据采样、配置生成 zingchart.render({ id: containerId, // 使用传入的容器ID data: configTimeAndAngle, height: "100%", width: "100%", output: 'webgl' }); } // 调用时指定对应容器 drawTimeVSAngleChart('chart1', data[0], data[1], data[2]);
4. 关闭高消耗功能
- 关闭实时预览:移除或修改
preview配置// 移除原有的preview配置,或者设置live为false // "preview":{"live":true} → 删除该行 - 优化tooltip触发逻辑,减少频繁渲染:
tooltip: { text: 'Time : %kt (X) Freq : %vt (Y).', delay: 300, // 添加300ms延迟,避免鼠标移动时频繁触发 alpha: 0.9, backgroundColor: '#F44336', borderColor: '#B71C1C', borderRadius: 2, borderWidth: 1, padding: '5 10' },
5. 分批加载与渲染
避免一次性加载80万+数据导致内存过载,分批加载4个图表:
// 待加载的表格列表 const tableNames = ['table1', 'table2', 'table3', 'table4']; let currentChartIndex = 0; function loadNextChart() { if (currentChartIndex >= tableNames.length) return; const tableName = tableNames[currentChartIndex]; $.ajax({ type: 'GET', cache: false, url: url, data: { startTime : '2022-07-25 10-40-12', endTime : '2022-08-22 17-41-14', tableName : tableName }, success: function (data) { drawTimeVSAngleChart(`chart${currentChartIndex + 1}`, data[0], data[1], data[2]); currentChartIndex++; loadNextChart(); // 加载完成后启动下一个 }, error: function (jqXHR, textStatus, errorThrown) { console.log(errorThrown); currentChartIndex++; loadNextChart(); // 出错仍继续加载下一个 } }); } // 启动分批加载 loadNextChart();
内容的提问来源于stack exchange,提问作者decent boy
相关产品推荐
相关产品推荐

