性能这个点上,单个元素的动画其实两者的差距很难看出来,不过可以不靠谱的说基于 gpu 的 css3 动画性能更好,具体得视动画的复杂度而定。两者在大量元素动画的情况下又如何呢。我们都知道大量 DOM 节点会导致性能垂直下降,如果我们需要对 10000 个 DOM 节点做动画,那么帧率可能不会可观。而 canvas 的大量 fillRect 调用的性能又会不会成为瓶颈呢?于是我们就采用对 10000 个元素做动画的方式进行测试:
相信很容易就能感受出来差别,那么为什么呢?
以下这段瞎扯,有误请大佬指正。css3 动画可以走 cpu 也可以走 gpu,transform 之类能够提供“参数”稳定的属性就能够通过 gpu 单独绘制 layer,这两种动画的性能完全不同。基于 gpu 的 css 动画,它的主要开销有:
CPU 与 GPU 通信的开销
composite 的开销
基于 cpu 的 css 动画,它的主要开销有:
layout,重新计算布局的开销
repaint,重新绘制图层的开销
composite 的开销
而 canvas 的主要开销主要是在:
执行 Javascript 的开销
Skia 绘制的开销
composite 的开销
看起来,好像好像确实是 canvas 的开销更多呀。但是由于测试用例中大量的 DOM 元素意味着大量图层需要进行合成工作,这才是拖垮性能的关键。
当然,讨论完性能,更重要的区别在于两者是适应不同场景的。当我们需要对已有的复杂 DOM 元素做动画,例如整个页面的动画效果,我们会考虑把它绘制到 canvas 上再去做动画吗?那显然不会,成本太高了,这个成本倒不是指渲染的成本,而是我们需要“复刻”这个 DOM 元素的成本;当我们需要完成一些 DOM 无法完成的高表现力的交互时,比如做一个画板,纯粹的 DOM 能做吗?或许 SVG 是一个选择,那如果是更复杂的场景呢?理论上来说 css3 动画能做的canvas 都能做,反之就不是这样。
至于 webgl 与 canvas 的区别,他两都能做 3D 也都能做 2D,只是谁更适合而已。性能上来说,大部分情况下 webgl 高出不少,毕竟直接走 gpu。canvas 在图像合成上也会走 gpu,其他的 API 还是在 cpu 通过 skia 绘制。虽然 webgl 性能好,但是学习门槛高多了,如果不用现有的库开发,需要不少的数学和图形学知识。