为什么在画布上填充矩形会慢慢降低性能?

时间:2015-02-16 04:49:45

标签: javascript html5 performance canvas

我目前正致力于使用<canvas>元素的HTML5游戏。随着时间的推移,我在程序中神秘地遭受了性能下降的困扰,并且希望你能解释一下这种行为。

我已经将问题追溯到绘制每个帧背景的函数。在要点中,它显示为:

function paintBackground() {
  ctx.rect(0, 0, canvas.width, canvas.height)
  ctx.fillStyle = "black"
  ctx.fill()
}

我还设置了代表此方案的JSFiddle

这段代码的有趣之处在于,经过测量,它会逐渐降低几个数量级的效率。以JSFiddle为例,它从函数开始不到一毫秒即可完成。大约2-3秒后,报告它现在需要大约1毫秒。大约10秒钟,它现在平均在2-3毫秒之间。在一分钟内平均大约6-7毫秒,当我让它运行大约5分钟时,它高达13-14毫秒。这比开始时慢几百%,没有任何变化!我在IE 11和Firefox 35.0.1中测试了相同的代码片段。两者都表现出同样的退化,但似乎在Firefox中下滑得更快。

现在,我不是那些迷恋微观恐慌的人,但我的目标是达到稳定的60FPS,这意味着我只有16.67ms的渲染和更新,我基本上逐渐失去了一半仅仅通过渲染背景就可以了!我也担心这可能是一辆失控的火车,谁知道性能有多糟糕;可能导致我的游戏无法播放。

据我所知,这是导致性能下降的唯一因素,原因有二:1)游戏代码的其余部分运行平稳,包括渲染所有的图块(每帧375+个图块)组成一个级别,2)我甚至在提供的JSFiddle中遇到这种行为,其中只包含矩形填充。

对这种行为的任何解释或建议都会有所启发!

P.S。我知道这可能听起来很愚蠢,但是其他人是否经历过这种行为?还是只是我?我应该注意到我的CPU足够慢(1.4ghz双核)以使其显着。

1 个答案:

答案 0 :(得分:4)

rect()命令将添加到路径并累积,因此每次调用fill()时,所有先前的矩形也都会被填充。

以两种方式解决:

function paintBackground() {
  ctx.beginPath(); // RESET path here
  ctx.rect(0, 0, canvas.width, canvas.height);
  ctx.fillStyle = "black";
  ctx.fill();
}

或直接填写而不使用路径:

function paintBackground() {
  ctx.fillStyle = "black";
  ctx.fillRect(0, 0, canvas.width, canvas.height);
}

还可以使用requestAnimationFrame来获得更好的动画效果。

<强> Modified fiddle

Ps:不要忘记半列。