Canvas 11

canvas的优化

性能提升的技巧

在离屏的canvas上预渲染相似的图形或重复的对象。

如果存在相同的绘制操作在每个动画帧上,我们可以考虑将其分流到屏幕的画布上。

myCanvas.offscreenCanvas = document.createElement("canvas");
myCanvas.offscreenCanvas.width = myCanvas.width;
myCanvas.offscreenCanvas.height = myCanvas.height;

myCanvas.getContext("2d").drawImage(myCanvas.offScreenCanvas, 0, 0);

myEntity.offscreenCanvas = document.createElement("canvas");
myEntity.offscreenCanvas.width = myEntity.width;
myEntity.offscreenCanvas.height = myEntity.height;
myEntity.offscreenContext = myEntity.offscreenCanvas.getContext("2d");

myEntity.render(myEntity.offscreenContext);

避免使用浮点数的像素,使用整数替代。

当我们绘制一个非整数的坐标点的对象时就会发生子像素渲染,但是会增加浏览器的额外运算。

不要使用drawImage进行图片的缩放

我们可以通过离屏画布预先加载渲染不同尺寸的图片,不使用drawImage中缩放

使用分层的画布在复杂的场景中

例如我们在应用中有一些需要频繁移动的元素,而其他一些元素需要保持相对不变。我们可以使用多个canvas元素进行部分分层渲染。

使用纯css添加大的背景图

使用css变换进行canvas画板的缩放

css transforms会使用GPU进行加速渲染页面,最好不要直接缩放画布,或者较小的画布按比例放大,而不是较大的画布按比例缩小。

var scaleX = window.innerWidth / canvas.width;
var scaleY = window.innerHeight / canvas.height;

var scaleToFit = Math.min(scaleX, scaleY);
var scaleToCover = Math.max(scaleX, scaleY);

stage.style.transformOrigin = "0 0"; //scale from top left
stage.style.transform = "scale(" + scaleToFit + ")";

关闭透明度

当我们的画布无需透明度,我们可以在获取上下文添加选项,帮助我们浏览器进行内部优化。

var ctx = canvas.getContext("2d", { alpha: false });

缩放高分辨率的显示器

当我们发现canvas画布内容在高分辨率的显示屏上显示模糊需要设置缩放一定的比例。

// Get the DPR and size of the canvas
const dpr = window.devicePixelRatio;
const rect = canvas.getBoundingClientRect();

1  // Set the "actual" size of the canvas
canvas.width = rect.width * dpr;
canvas.height = rect.height * dpr;

2  // Scale the context to ensure correct drawing operations
ctx.scale(dpr, dpr);

3  // Set the "drawn" size of the canvas
canvas.style.width = `${rect.width}px`;
canvas.style.height = `${rect.height}px`;

  • 批量绘制操作,不是一根根折线绘制,而是一起绘制。
  • 避免非必要的画布状态改变
  • 避免使用shadowBlur属性扩大阴影
  • 差异渲染
  • 尽可能避免文本渲染
  • 绘制动画时尽量使用window.requestAnimationFrame()
  • 谨慎使用一些大型的物理库

写在最后

未完待续…
希望大家好好生活,健康快乐。