前面我们在《6.增量计算》一文中介绍了滚动过程中的增量渲染方案,通过减少渲染计算量或绘制量的方式,来提升页面滚动的流畅度。
除此之外,当滚动距离较远时,增量渲染并不能达到预期的优化效果,此时我看还需要考虑降级渲染。
# 页面内的元素优先级划分
当用户打开一个大的页面时,除了使用搜索获取关键信息,还可能会快速滚动来翻阅整体内容,然后找到关注的信息进行详细查阅。增量渲染的方案,核心是将上一帧的内容尽可能复用到下一帧里,因此在快速滚动的场景下(比如拖动滚动条滚动),页面中可能并没有多少可复用的内容。
在这样的场景下,如果需要渲染的内容实在很多,我们可以对页面内容进行优先级划分。
该如何进行优先级划分呢?这个可能需要结合业务的具体情况进行分析,比如:
- 分段分组的内容:标题、副标题等
- 方便用户定位位置的内容:文本框、图片、背景色等
像图片这种渲染可能会比较耗时,那么可以用占位符等方式来进行骨架渲染,让用户能快速定位到对应位置之后,再进行详细内容的渲染。
具体到在线表格的场景下,首先行列位置十分重要,同时方便用户定位位置的还有单元格背景色、边框线、图片等等内容。我们可以这样拆分优先级:
- 行列头、行列序号、选区
- 单元格背景色、边框线
- 图片(占位符)
- 文本内容
- 其他格式内容/图标(格式错误角标、下拉按钮、icon 内容等)
- 真实图片信息
- 其他
拆分出优先级后,我们可以进行降级的渲染,在流畅度不高的情况下,优先渲染高优先级的内容,保证用户的滚动流畅体验。
# 降级渲染
通过优先级的划分,我们可以在渲染过程中,保证滚动操作的流畅度。具体方式为:根据页面帧率和用户滚动的距离,来进行降级的渲染。
# 页面帧率
理想情况下,检测到页面帧率开始下降的情况下,则考虑进入降级渲染的场景。
页面帧率可以使用requestAnimationFrame
来进行计算,当然前提还需要是页面进行了滚动操作,否则的话只是单纯当前页面绘制慢则进行降级,用户会感觉页面内容突然减少,体验较差。
我们可以在页面开始滚动时,监听 rAF 变化来计算 FPS,当 FPS 明显下降到不流畅的时候,则进入降级渲染,并根据帧率来调整降级渲染的级数。比如(简单举例):
0 < FPS < 10
: 最高级别的降级渲染,只渲染边框线和单元格背景色10 < FPS < 20
: 中级别的降级渲染,除了边框线和单元格背景色以外,还渲染单元格富文本内容20 < FPS < 30
: 低级别的降级渲染,除了边框线和单元格背景色、单元格以外,还渲染图片30 < FPS < 40
: 最低级别的降级渲染,渲染仅附加内容(如角标、协作者光标、icon 等)以外的内容
# 滚动距离
在很多情况下,其实我们并不能很好地使用requestAnimationFrame
来计算 FPS 帧率,因为 FPS 的计算需要一个累计过程,才能得到平均 1s 内的平均 FPS,同时频繁使用 rAF 本身也可能会影响到页面渲染性能。
所以,我们可以从别的角度来控制降级渲染的情况,比如使用用户页面滚动的快慢来控制优先级。
我们依然可以使用渲染本身,在两次渲染之间获取用户的滚动距离,根据滚动距离判断滚动速度,并以此来调整降级渲染的策略。比如,当页面进入滚动状态后,两次绘制之间的滚动距离:
- 超过 20 屏内容:最高级别的降级渲染
- 10 屏 < 滚动距离 < 20 屏:中级别的降级渲染
- 5 屏 < 滚动距离 < 10 屏:低级别的降级渲染
- 2 屏 < 滚动距离 < 5 屏:最低级别的降级渲染
当然,这里的渲染,除了 rAF 本身之外,还可以是 API 的调用如渲染层的 render 接口,或者是 canvas 的绘制。
# 渲染插件的降级
前面在《2.插件的实现》一文中,我们介绍了除核心渲染内容以外,其他附加格式内容的渲染方式:使用渲染插件。
由于插件设计的存在,我们通过很简单的方式,就能实现降级渲染的能力。因为一些附加格式的渲染,都是使用渲染插件实现的,比如 icon 绘制、下拉菜单、角标、图片等等,我们可以十分轻易地将渲染插件进行降级优先级的归档。
当我们判断需要进行降级渲染时,可以直接通过优先级策略,来控制是否跳过某些插件的收集过程,便可以直接达到降级渲染的效果。
# 降级渲染的启动和停止
前面提到,进入降级渲染的前提条件是用户进行滚动,在滚动过程中通过不同的方式判断用户滚动“是否流畅”,如果检测到滚动不流畅的话,则根据卡顿程度进入到不同级别的降级渲染。
降级渲染,说白了就是减少页面渲染的内容,从而减轻每次渲染的耗时,提升用户的使用流畅度。
但当用户停止滚动、或是滚动较慢时,这时候可以认为用户需要聚焦阅读页面中的信息,因此这种时候我们还需要退出降级渲染模式,将页面内容进行完整渲染。
通过这样的方式,我们保证了用户滚动流畅度的同时,还确保了页面内容不会丢失。
# 结束语
本文介绍了当页面内容过多,用户在滚动时因为绘制较慢导致不流畅时,使用降级渲染的方式来保证用户的流畅度。
当然,其实说到底这个策略也会损耗了一些用户体验,但如果有更好的优化方式,我们也不需要使用到降级策略。很多时候,技术的决策便是在各种不同优劣的技术方案中,选出一种性价比更好、投入产出比更好的方案而已。