你知道一些关于画布的最佳实践吗??
请将您所知道的、学到的或在线阅读的任何和所有 Canvas 最佳实践、性能提示/技巧添加到此线程
由于 Canvas 对互联网来说仍然很新,而且我在未来看不到它会变老的迹象,因此没有太多记录在案的“最佳实践”或其他真正重要的技巧,这些技巧对于开发来说是“必须知道的”它在任何一个特定的地方。像这样的事情在鲜为人知的网站上多次散布。
人们需要了解的东西太多了,还有很多东西需要学习。
我想分享一些东西来帮助那些正在学习 Canvas 的人,也许一些已经很了解它的人,我希望从其他人那里得到一些反馈,让他们知道在 HTML5 中使用 Canvas 的一些最佳实践或其他技巧和窍门.
我想从我个人认为对开发人员来说非常有用但非常罕见的事情开始。
1. 缩进你的代码
就像您在其他任何时候一样,无论情况如何,都可以使用任何其他语言。这一直是其他一切的最佳实践,我发现在复杂的画布应用程序中,在处理多个不同的上下文和保存/恢复状态时,事情可能会变得有点混乱。更不用说代码更具可读性,整体看起来也更干净。
例如:
...
// Try to tell me this doesn't make sense to do
ctx.fillStyle = 'red';
ctx.fill();
ctx.save();
if (thing < 3) {
// indenting
ctx.beginPath();
ctx.arc(2, 6, 11, 0, Math.PI*2, true);
ctx.closePath();
ctx.beginPath();
ctx.moveTo(20, 40);
ctx.lineTo(10, 200);
ctx.moveTo(20, 40);
ctx.lineTo(100, 40);
ctx.closePath();
ctx.save();
ctx.fillStyle = 'blue'
ctx.fill();
ctx.restore();
} else {
// no indenting
ctx.drawImage(img, 0, 0, 200, 200);
ctx.save();
ctx.shadowBlur();
ctx.beginPath();
ctx.arc(2, 60, 10, 0, Math.PI*2, false);
ctx.closePath();
ctx.fillStyle 'green';
ctx.fill();
ctx.restore();
}
ctx.restore();
ctx.drawRect();
ctx.fill();
...
IF 语句不是比 ELSE 语句更易于阅读和更清晰的阅读并了解立即发生的事情吗?你能看到我在这里说什么吗?我认为这应该是开发人员应该继续练习的一种方法,就像他们在编写普通的 'ol javascript 或任何其他语言时一样。
使用 requestAnimationFrame 而不是 setInterval / setTimeout
setInterval 和 setTimeout 从未打算用作动画计时器,它们只是用于在时间延迟后调用函数的通用方法。如果您将来将间隔设置为 20 毫秒,但您的函数队列需要比执行时间更长的时间,则在这些函数完成之前,您的计时器不会触发。这可能需要一段时间,这在动画方面并不理想。RequestAnimationFrame是一种告诉浏览器正在发生动画的方法,因此它可以相应地优化重绘。它还会限制非活动选项卡的动画,因此如果您将其在后台打开,它不会耗尽移动设备的电池。
Nicholas Zakas在他的博客上写了一篇关于 requestAnimationFrame的非常详细和翔实的文章,非常值得一读。如果您想要一些严格而快速的实施说明,那么Paul Irish 编写了一个 requestAnimationFrame shim – 这是我最近在我制作的每个 Canvas 应用程序中使用的内容。
实际上
甚至比使用 requestAnimationFrame 代替 setTimeout 和 setInterval 更好,Joe Lambert 编写了一个新的和改进的垫片,称为 requestInterval 和 requestTimeout,他解释了使用 requestAnimFrame 时存在的问题。您可以查看脚本的要点。
实际 x2
现在所有的浏览器都已经赶上了这个规范,requestAnimFrame() polyfill已经更新了,它可能会继续用于覆盖所有供应商。
使用多个画布
@nicolahibbert在她的一篇关于优化 Canvas 游戏的帖子中提到了一种用于大量动画游戏的技术,其中提到最好使用多个叠加在一起的画布,而不是在一个画布中完成所有工作。Nicola 解释说,“在同一画布上同时绘制太多像素会导致帧率下降。以 Breakout 为例。尝试绘制砖块、球、桨、任何电源或武器, 然后是背景中的每个星星——这根本行不通,依次执行这些指令需要很长时间。通过将星空和游戏的其余部分拆分到单独的画布上,您可以确保体面的帧率。”
在屏幕外渲染元素
我不得不为我制作的一些应用程序执行此操作,包括三星的奥林匹克基因组项目 facebook 应用程序。了解并利用它是否需要,这是一件非常有用的事情。它极大地减少了加载时间,而且它可以是一种非常有用的技术,可以将图像加载到屏幕外,因为它们有时需要一段时间。
var tmpCanvas = document.createElement('canvas'),
tmpCtx = tmpCanvas.getContext('2d'),
img = document.createElement('img');
img.onload = function() {
tmpCtx.drawImage(thumbImg, 0, 0, 200, 200);
};
img.src = '/some/image/source.png';
请注意,图像的 src 是在加载后设置的。这也是要记住做的关键事情。一旦图像完成加载并绘制到这些临时画布中,您就可以使用相同的 ctx.drawImage() 将它们绘制到主画布上,但不是将图像作为第一个参数,而是使用 'tmpCtx.canvas'引用临时画布。
其他提示、技巧和资源
Canvas 有一个反向引用
2d 上下文具有对其关联 DOM 元素的反向引用:
var ctx = doc.getElementById('canvas').getContext('2d');
console.log(ctx.canvas); // HTMLCanvasElement
我很想从其他人那里听到更多关于这方面的信息。我正在制定一份清单,列出我们应该标准化的内容,以便在我公司的前端代码标准和最佳实践中添加一个新部分。我很想得到尽可能多的反馈。