4

我刚开始玩 HTML5 画布,我希望能用它制作一些游戏。然而,当我开始向它渲染鼠标坐标时,它几乎停止了:

http://jsfiddle.net/mnpenner/zHpgV/

我所做的只是渲染 38 行和一些文本,它应该能够处理,不是吗?

难道我做错了什么?我希望能够以至少 30 FPS 的速度进行渲染,但是对于这样的事情,我希望它能够绘制 1000 次。

还是我只是在工作中使用了错误的工具?WebGL 能胜任这项任务吗?为什么一个会比另一个慢这么多?

String.prototype.format = function() {
    var args = arguments;
    return this.replace(/\{(\d+)\}/g, function(m, n) {
        return args[n];
    });
};
var $canvas = $('#canvas');
var c = $canvas[0].getContext('2d');
var scale = 20;
var xMult = $canvas.width() / scale;
var yMult = $canvas.height() / scale;
var mouseX = 0;
var mouseY = 0;
c.scale(xMult, yMult);
c.lineWidth = 1 / scale;
c.font = '1pt Calibri';

function render() {
    c.fillStyle = '#dcb25c';
    c.fillRect(0, 0, scale, scale);
    c.fillStyle = '#544423';
    c.lineCap = 'square';
    for (var i = 0; i <= 19; ++i) {
        var j = 0.5 + i;
        c.moveTo(j, 0.5);
        c.lineTo(j, 19.5);
        c.stroke();
        c.moveTo(0.5, j);
        c.lineTo(19.5, j);
        c.stroke();
    }
    c.fillStyle = '#ffffff';
    c.fillText('{0}, {1}'.format(mouseX, mouseY), 0.5, 1.5);
}
render();
$canvas.mousemove(function(e) {
    mouseX = e.clientX;
    mouseY = e.clientY;
    render();
});
<canvas id="canvas" width="570" height="570"></canvas>

4

3 回答 3

10

这是代码变得更好。

http://jsfiddle.net/zHpgV/3/

以下是我更改后您应该考虑的事项的细分:

  • 连续添加到路径而不是停止并使用beginPath. 这是迄今为止最大的性能杀手。您最终会得到一条包含成千上万条线段的路径,这些线段永远不会被清除。
  • 当只需要创建一次时,在初始化时不断地重复创建相同的路径。也就是说,您唯一需要在内部调用的renderstroke. 你不需要再打电话lineTo/moveTo了,当然也不需要连续打电话。见注 1。
  • 为一条路径抚摸两次
  • 在 for 循环中抚摸
  • 重绘背景而不是设置 CSS 背景
  • 一遍又一遍地设置线路上限

注意 1:如果您计划在应用程序中拥有多个路径,那么您可能应该缓存这样的路径,因为它们永远不会改变。我有一个关于如何做到这一点的教程

当然,如果您这样做只是为了制作背景,则应将其保存为 png,并且您应该使用 CSS 背景图像。

像这样:http: //jsfiddle.net/zHpgV/4/

然后突然你的渲染例程相当小:

function render() {
    c.clearRect(0, 0, scale, scale);
    c.fillText('{0}, {1}'.format(mouseX, mouseY), 0.5, 1.5);
}
于 2012-06-22T20:29:41.063 回答
9

正如我在评论中所说,我对这段代码的缓慢感到惊讶,因为我用非常快的动画绘制了更复杂的东西,甚至没有考虑双缓冲。

于是我又看了看,果然发现了一个bug。

主要问题是绘制路径的积累。

c.beginPath();每次绘制一条路径时添加一个。

这是同一事物的快速渲染,以证明它现在可以运行。

画布绘图速度很快,可用于动画。

于 2012-06-22T17:41:14.057 回答
7

您不必在每个动画帧中绘制整个网格。将它放在另一个底层画布上(通常称它们为“层”,但它们只是单独的画布元素),因此您只能重绘坐标。

<div id="canv">
 <canvas id="bgLayer" width="500" height="500" style="z-index: 0"></canvas>
 <canvas id="fgLayer"  width="500" height="500" style="z-index: 1"></canvas>
</div>

这是我一直在使用分层画布的示例。表格绘制在底部画布上,球绘制在顶部画布上。它只是一个游乐场,因此有很多需要修复和优化的地方,例如在另一个隐藏的画布上只绘制每个球一次,并使用getImageData/putImageData来提高性能。

另外,推荐使用requestAnimationFrame来更新画布。相反,您的示例利用了每次鼠标移动,这比需要更频繁(当然,当鼠标移动时)。

有一篇关于提高画布性能的好文章。此外,关于这个主题还有一篇很棒的SO 帖子。

于 2012-06-22T06:01:22.747 回答