canvas 绘制各种动画效果时,我们经常会使用画布旋转,使绘制上去的元素有旋转的效果。

  最近在项目中碰到了很严重的性能问题,经常排查发现是因为绘制批量文字时使用了画布旋转,且每行文字的旋转角度是不一样的,每次绘制前都会去动态的改变画布上下文context的旋转角度值,导致CPU占用太多。

  而且发现如果绘制的不是文字元素,而是其他路径类如:rect arc等路径时,cpu并不会飙升。

  text旋转后绘制性能低于canvas其他路径类,下面给大家看下测试的结果:

  有如下代码:分别绘制100个文字,并设置了旋转角度,设置50ms绘制一遍

 1 <html>
 2
 3 <head></head>
 4
 5 <body>
 6     <div>
 7         <canvas id="canvas" width="1920" height="1080"></canvas>
 8
 9     </div>
10     <script>
11         let canvas = document.getElementById("canvas");
12         let ctx = canvas.getContext('2d');
13         //测试绘制旋转文字的性能
14         setInterval(drawText, 50);
15         //测试绘制旋转矩形的性能
16         // setInterval(drawRect, 50);
17
18         function drawRect() {
19             ctx.clearRect(0, 0, 1920, 1080);
20             for (let i = 0; i <= 500; i += 5) {
21                 ctx.save();
22                 ctx.beginPath();
23                 rotateContext(ctx, 500, 500, i * Math.random());
24                 ctx.fillStyle = "red";
25                 ctx.rect(250, i + 250, 20, 10);
26                 ctx.fill();
27                 ctx.restore();
28             }
29         }
30         function drawText() {
31             ctx.clearRect(0, 0, 1920, 1080);
32             for (let i = 0; i <= 500; i += 5) {
33                 ctx.save();
34                 ctx.beginPath();
35                 rotateContext(ctx, 500, 500, i * Math.random());
36                 ctx.fillStyle = "red";
37                 ctx.fillText("反倒是的", 250, i + 250);
38                 ctx.restore();
39             }
40         }
41         //确保是以(x,y)为中心进行旋转,而不是简单的以画布原点旋转
42         function rotateContext(ctx, x, y, degree) {
43             ctx.translate(x, y);
44             ctx.rotate(degree * Math.PI / 180);
45             ctx.translate(-x, -y);
46         }
47
48     </script>
49 </body>
50
51 </html>

  绘制效果如下:

  可以观察浏览器里面的性能指标,已经接近100%

测试canvas绘制旋转文字的性能-LMLPHP

  而如果我们绘制的是100个矩形,同样设置旋转角度

  把上面代码段中的drawRect循环绘制的代码行t放开,注释掉drawText循环绘制。再看绘制效果,和drawText的效果是一样的。

   而此时的在浏览器里观察cpu占用的就非常低

测试canvas绘制旋转文字的性能-LMLPHP

  至于为什么有这个问题,还需要深入学习canvas绘制文字的方式,希望有研究的同学能够分享给大家!

11-13 18:32