在使用 ECharts 处理大数据场景时,我们发现触发高亮效果后,顶层 Canvas 出现图像残影未及时清理的问题。本文记录了问题的复现过程、可能的原因分析以及最终的解决方案。
问题描述
在客户环境下测试时,接口返回了大量数据。在本地重现时,我们稳定复现了以下问题:
- 图表渲染后不触发 hover 操作,不会出现异常。
- 一旦触发了 x 坐标轴的高亮效果,会在顶层 Canvas 留下残影,并且残影不会随鼠标移动或图表刷新而消失。
通过观察 DOM 结构,发现这些异常的 Canvas 节点具有属性 data-zr-dom-id="zr_100000"
。
相关现象
- 只有触发 hover 操作时才会产生残影。
- 残影问题在大数据量场景中稳定复现。
- 通过分析源码和社区反馈,初步判断是 ECharts 在大数据场景下的 Canvas 分层优化策略存在问题。
原因分析
ECharts 在处理大数据时,会对 Canvas 进行分层优化。高亮效果被渲染到顶层的 Canvas,但在某些情况下,这一层没有被正确刷新,从而导致残影问题。
根本原因在于:一次性触发了太多内容(如一个 Category 中包含过多的散点、折线或箱图),导致高亮效果的刷新逻辑未能正确处理所有数据。
社区资料参考
虽然未找到直接相关的资料,但以下链接提供了一些背景信息:
- zr_100000
- ECharts 3.0 底层 zrender 3.x 源码分析
- GitHub Issue #14875: High CPU overload and user interaction freeze
解决方案
经过分析和多次尝试,最终我们决定从配置入手,禁用可能引发问题的高亮效果。
禁用高亮效果的实现
我们在 ECharts 的配置项中注释掉了 axisPointer
的相关配置:
return {
grid: finalGrid,
xAxis: [...xAxis, ...xAxisExtends],
yAxis: [...yAxis, ...yAxisExtends],
series: finalSeries,
tooltip: {
show: true,
confine: true,
// 大数据场景下一次性触发太多高亮效果会有残影问题
// axisPointer: {
// axis: 'auto',
// type: 'cross',
// },
},
legend: { show: true, top: -10000, width: 10000, data: boxPlotData.colorBys },
xAxisConfList: finalXAxisConfList,
dataZoom,
} as EChartsOption;
配置项说明
- tooltip.axisPointer:
axisPointer
是导致残影的主要原因。在大数据场景中禁用该功能,可以有效避免问题。 - legend.top 和 legend.width: 用于调整图例显示,避免占用太多空间。
优化后的效果
禁用 axisPointer
后,我们重新测试了以下场景:
- 渲染后的静态图表。
- 图表中鼠标 hover 触发高亮效果。
结果显示,残影问题已完全解决,图表交互性能也有所提升。
总结
ECharts 在大数据场景下提供了强大的渲染能力,但一些高级功能(如 axisPointer
)可能在极端场景中引发问题。根本原因是一次性触发了过多内容,导致刷新逻辑未能完全处理。通过合理简化配置,可以在保证功能性的同时,避免性能和交互上的潜在问题。
如果你也遇到类似问题,可以尝试调整配置,禁用高亮效果,或优化数据量和渲染方式。
当然,以下是为你原有博客结尾部分自然补充的段落内容:
【2025.4.8 更新】配置无法完全解决,需手动隐藏残影层
在进一步测试中我们发现,即使禁用了 axisPointer
,在某些场景下仍会出现残影问题,尤其是当用户将鼠标悬停在 ECharts 原生图例(Legend)上时,仍然会触发图中高亮效果,并导致残影堆积。
进一步排查发现,这些残影来自于顶层 Canvas 节点 data-zr-dom-id="zr_100000"
,即 zrender 为高亮效果单独维护的图层。而这个图层的刷新机制在大数据量场景下会失效,导致图像无法及时清除。
由于该联动高亮行为无法通过配置项取消,因此我们采取了手动隐藏高亮图层的方式作为兜底方案:
/* 禁用 echarts 部分图表的高亮图层(大数据量场景下存在残影问题) */
.guwave-echarts-zr100000-mask--disable-layer canvas[data-zr-dom-id='zr_100000'] {
display: none !important;
}
你可以将这段样式添加到图表容器所在区域的作用域内,必要时加上对应的类名控制范围。
⚠️ 注意:这并非官方推荐做法,而是针对当前版本 ECharts 在高数据量下渲染逻辑缺陷的一个临时性规避手段。
🧩 最终结论:
- 残影问题的根本原因是 ECharts 在大数据场景下,zrender 的顶层高亮 Canvas 没有及时刷新;
- 配置项如
axisPointer
可缓解大部分问题,但对于图例联动高亮无效;- 彻底规避残影问题的唯一方式,是完全关闭高亮逻辑,或者手动隐藏顶层 Canvas;
- 此问题属于 ECharts 库本身的渲染优化缺陷,与业务代码无关,建议在产品上线前评估相关功能必要性。
如果你也被这个 bug 折磨,希望这篇记录能为你节省一些排查时间!
Comments NOTHING