简介
前面章节里面讨论过图形的局部渲染,但是当调用局部渲染频率过高时性能不升反降,所以需要控制渲染的频率。我们常用的技术主要有:debounce 和 throttle,而在我们的渲染场景更适合 throttle ,要保证 16ms 内必须要渲染一次,我们有两种方案来实现 throttle。
方案
有两种方案来实现延迟渲染:
- 在一段时间 16ms 内调用 n 次渲染,保证渲染两次,第一次和最后一次
- 在一段时间 16ms 内调用 n 次渲染,仅渲染一次,最后一次
这两种方案都是通过抛弃无效的渲染来实现,唯一的差异在于第一种方案要渲染两次。
绘制两次
绘制两次的实现如下:
- 用户第一次调用 draw 时,马上绘制,然后启动一个 setTimeout(function(){}, 16);
- 用户在 16ms 再次调用 draw 时,不绘制仅设置 toDraw = true
- setTimeout 触发时,判定如果存在 toDraw=true,立刻进行下一次绘制
绘制一次
绘制一次的步骤如下:
- 用户第一次调用 draw 时不立刻绘制,而启动 setTimeout(function(){}, 16);
- 用户在 16ms 再次调用 draw 时,直接返回什么也不处理
- setTimeout 触发时,进行绘制
优劣对比
我们通过两种情况来对比两种方案的优劣:
- 一次渲染的时长小于 16ms
- 一次渲染的时长大于 16ms
一次渲染小于 16ms 时
如果一次渲染的时长小于 16ms 时,进行连续的绘制,其绘制如下图所示,方案一比方案二仅多一次绘制
一次渲染大于 16ms 时
情况比渲染小于 16ms 时复杂,我们可以看到方案一的渲染是连续的,而方案二的渲染中间必定出现 16ms 的延迟。
对比
方案一:
- 优点:
- 保证马上绘制:在测试时方便,不需要进行延迟测试;动画的执行也比较准确
- 绘制帧率高,相同时间内能够渲染的帧数要比第二种方案高
- 缺点:
- 实现复杂,代码不易于理解
- 渲染过程中没有中断,没有留出交互反馈的时间
方案二
- 优点:
- 实现简单,易于理解
- 两次渲染中间给交互留出了响应时间
- 缺点:
- 测试困难,动画的执行时间不准确
- 渲染会有延迟,相同时间内绘制的帧数低,如果在数据量非常大的情况下拾取时间 + 16ms 的延迟,能够出现明显的卡顿效果
使用 requestAnimationFrame
如果改成 requestAnimationFrame 会有些变化,requestAnimationFrame 的特性决定了每次触发发生在浏览器绘制一帧前,更多阅读参考 mozilla 的文档。
一次渲染小于 16ms 时
一次渲染大于 16ms 时
换成 requestAnimationFrame 后两者的差异依然是前者会多绘制一帧,优缺点依然保持。
总结
本章我们给出了两种延迟渲染的方案,同时给出了优劣的对比。G 中目前采用方案二,在后面的实践中如果发现问题可能会切换到方案一,如果要完美的解决帧率、性能、交互反馈等问题,可能要搭配分片渲染才能达到目的。
欢迎给出你的反馈!