在使用 ECharts 处理大数据场景时,我们发现触发高亮效果后,顶层 Canvas 出现图像残影未及时清理的问题。本文记录了问题的复现过程、可能的原因分析以及最终的解决方案。

问题描述

在客户环境下测试时,接口返回了大量数据。在本地重现时,我们稳定复现了以下问题:

  1. 图表渲染后不触发 hover 操作,不会出现异常。
  2. 一旦触发了 x 坐标轴的高亮效果,会在顶层 Canvas 留下残影,并且残影不会随鼠标移动或图表刷新而消失。

通过观察 DOM 结构,发现这些异常的 Canvas 节点具有属性 data-zr-dom-id="zr_100000"

Snipaste_2024-12-26_10-25-03.png

相关现象

%E6%88%AA%E5%B1%8F2024-12-26%2011.03.19.png

  • 只有触发 hover 操作时才会产生残影。
  • 残影问题在大数据量场景中稳定复现。
  • 通过分析源码和社区反馈,初步判断是 ECharts 在大数据场景下的 Canvas 分层优化策略存在问题。

原因分析

ECharts 在处理大数据时,会对 Canvas 进行分层优化。高亮效果被渲染到顶层的 Canvas,但在某些情况下,这一层没有被正确刷新,从而导致残影问题。

根本原因在于:一次性触发了太多内容(如一个 Category 中包含过多的散点、折线或箱图),导致高亮效果的刷新逻辑未能正确处理所有数据。

社区资料参考

虽然未找到直接相关的资料,但以下链接提供了一些背景信息:

解决方案

经过分析和多次尝试,最终我们决定从配置入手,禁用可能引发问题的高亮效果。

禁用高亮效果的实现

我们在 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 后,我们重新测试了以下场景:

  1. 渲染后的静态图表。
  2. 图表中鼠标 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 折磨,希望这篇记录能为你节省一些排查时间!


A Student on the way to full stack of Web3.