canvas 绘制各种动画效果时, 我们经常会使用画布旋转, 使绘制上去的元素有旋转的效果.
最近在项目中碰到了很严重的性能问题, 经常排查发现是因为绘制批量文字时使用了画布旋转, 且每行文字的旋转角度是不一样的, 每次绘制前都会去动态的改变画布上下文 context 的旋转角度值, 导致 CPU 占用太多.
而且发现如果绘制的不是文字元素, 而是其他路径类如: rect arc 等路径时, CPU 并不会飙升.
text 旋转后绘制性能低于 canvas 其他路径类, 下面给大家看下测试的结果:
有如下代码: 分别绘制 100 个文字, 并设置了旋转角度, 设置 50ms 绘制一遍
- <html>
- <head></head>
- <body>
- <div>
- <canvas id="canvas" width="1920" height="1080"></canvas>
- </div>
- <script>
- let canvas = document.getElementById("canvas");
- let ctx = canvas.getContext('2d');
- // 测试绘制旋转文字的性能
- setInterval(drawText, 50);
- // 测试绘制旋转矩形的性能
- // setInterval(drawRect, 50);
- function drawRect() {
- ctx.clearRect(0, 0, 1920, 1080);
- for (let i = 0; i <= 500; i += 5) {
- ctx.save();
- ctx.beginPath();
- rotateContext(ctx, 500, 500, i * Math.random());
- ctx.fillStyle = "red";
- ctx.rect(250, i + 250, 20, 10);
- ctx.fill();
- ctx.restore();
- }
- }
- function drawText() {
- ctx.clearRect(0, 0, 1920, 1080);
- for (let i = 0; i <= 500; i += 5) {
- ctx.save();
- ctx.beginPath();
- rotateContext(ctx, 500, 500, i * Math.random());
- ctx.fillStyle = "red";
- ctx.fillText("反倒是的", 250, i + 250);
- ctx.restore();
- }
- }
- // 确保是以 (x,y) 为中心进行旋转, 而不是简单的以画布原点旋转
- function rotateContext(ctx, x, y, degree) {
- ctx.translate(x, y);
- ctx.rotate(degree * Math.PI / 180);
- ctx.translate(-x, -y);
- }
- </script>
- </body>
- </HTML>
绘制效果如下:
可以观察浏览器里面的性能指标, 已经接近 100%
而如果我们绘制的是 100 个矩形, 同样设置旋转角度
把上面代码段中的 drawRect 循环绘制的代码行 t 放开, 注释掉 drawText 循环绘制. 再看绘制效果, 和 drawText 的效果是一样的.
而此时的在浏览器里观察 CPU 占用的就非常低
至于为什么有这个问题, 还需要深入学习 canvas 绘制文字的方式, 希望有研究的同学能够分享给大家!
来源: https://www.cnblogs.com/fangsmile/p/9947823.html