# 拓扑图虚拟渲染
# 背景
原拓扑图中,在几千个设备时,浏览器就会很卡顿,操作通常需要几秒钟才有反应,体验十分差。
当时也做了相关的性能优化,比如开启g6的enableOptimize
,这会在拖动和缩放时,只显示图形的keyShape,这样可以减少同时操作的图元的元素,但在几千数量的时候,一样会卡顿。
那么还有什么好办法吗?借鉴表格的虚拟列表来的灵感,能不能只渲染可视范围中的图形呢?
# 实现
# 监听事件
首先,我们需要监听滚动和缩放事件,之前已经写过了graph-zoom
、drag-canvas-select
,在这两个行为中,有去监听事件,我们判断当设备数量大于200时再开启虚拟渲染(数量少时不需要)。
示例:
'canvas:dragstart': 'onDragstart'
[CUSTOM_EVENT.zoom]: 'debounceOnZoom'
当然,为了减少重复操作,我们需要做一个节流,这里设置200ms。
# 处理数据
事件触发后,收集所有的node和edge,通过自身的包围盒坐标与视口坐标判断是否在可视范围内,如果存在则渲染出来,否则隐藏掉。
当然,为了显示效果的流畅,视口这个范围不是用的真实的,而是加了500尺寸的缓冲区,避免拖的过程中出现空白。
需要注意的是,之前动态计算坐标是获取所有未隐藏的节点去计算,现在虚拟渲染给隐藏了,就需要特殊处理一下,判断是虚拟渲染给隐藏的也要参数坐标的计算。
另外存在收起的节点,这种需要判断父节点的展开收起状态,如果是收起的则可以不处理。
# 效果对比
测试4000台设备:
优化前,基本只能15~30帧,操作能明显感到卡顿,基本会延迟1s
优化后,基本在50帧以上,操作与数量少时几乎感觉不出差异。
由于优化后只渲染了可视部分,所以且当数量越大时,效果越明显。
并且在显示上,只显示keyShape会让人感到疑惑,而虚拟渲染则是显示全部图形,效果也更好。