# 拓扑图虚拟渲染

# 背景

原拓扑图中,在几千个设备时,浏览器就会很卡顿,操作通常需要几秒钟才有反应,体验十分差。

当时也做了相关的性能优化,比如开启g6的enableOptimize,这会在拖动和缩放时,只显示图形的keyShape,这样可以减少同时操作的图元的元素,但在几千数量的时候,一样会卡顿。

那么还有什么好办法吗?借鉴表格的虚拟列表来的灵感,能不能只渲染可视范围中的图形呢?

# 实现

# 监听事件

首先,我们需要监听滚动和缩放事件,之前已经写过了graph-zoomdrag-canvas-select,在这两个行为中,有去监听事件,我们判断当设备数量大于200时再开启虚拟渲染(数量少时不需要)。

示例:

'canvas:dragstart': 'onDragstart'
[CUSTOM_EVENT.zoom]: 'debounceOnZoom'

当然,为了减少重复操作,我们需要做一个节流,这里设置200ms。

# 处理数据

事件触发后,收集所有的node和edge,通过自身的包围盒坐标与视口坐标判断是否在可视范围内,如果存在则渲染出来,否则隐藏掉。

当然,为了显示效果的流畅,视口这个范围不是用的真实的,而是加了500尺寸的缓冲区,避免拖的过程中出现空白。

需要注意的是,之前动态计算坐标是获取所有未隐藏的节点去计算,现在虚拟渲染给隐藏了,就需要特殊处理一下,判断是虚拟渲染给隐藏的也要参数坐标的计算。

另外存在收起的节点,这种需要判断父节点的展开收起状态,如果是收起的则可以不处理。

# 效果对比

测试4000台设备:

优化前,基本只能15~30帧,操作能明显感到卡顿,基本会延迟1s

优化后,基本在50帧以上,操作与数量少时几乎感觉不出差异。

由于优化后只渲染了可视部分,所以且当数量越大时,效果越明显。

并且在显示上,只显示keyShape会让人感到疑惑,而虚拟渲染则是显示全部图形,效果也更好。