context.clearRect()真的很贵吗?

时间:2013-05-13 18:55:47

标签: javascript html5 performance canvas html5-canvas

我有一块画布动画,展现出一些奇怪的特征:

http://jsbin.com/olasol/2/edit

我使用的是Chrome的最新版本。我正在使用Chrome的内置FPS监视器(您可以通过转到about:flags激活它)。 我在JavaScript部分标记了这一行,我认为这是潜在的罪魁祸首:

fallingctx.clear();

这条线没什么特别的。它调用一个函数,然后调用clearRect()

我注意到的“奇怪”事情是:

  1. clear();功能会在我的笔记本电脑(Core 2 Duo)上造成非常明显的FPS下降,但不会在我的桌面上(i5 2500k)。

  2. 单独删除该行也足以在我的笔记本电脑上产生60fps。正如预期的那样,画布在每帧之后都不会清晰,但仍然会产生稳定的60fps。

  3. 只有当我的Chrome窗口偏大时才会发生FPS丢弃!当我缩小窗口并重新加载时,它不会发生! (清除更大的矩形是否更昂贵?)。

  4. 我尝试用clear()全白JPEG替换drawImage()来覆盖画布。对于较小的图像粒子,JavaScript能够在每个周期执行200 drawImage()次执行(从第二点可以看出)。但是,当我为整个画布添加一个drawImage时,它再次滞后! (确保输出占据整个屏幕以重现结果。)

  5. 为什么会发生这一切?我该如何解决?

1 个答案:

答案 0 :(得分:2)

真的取决于硬件,但想想clearRect的调用必须做什么!有些东西本质上必须将一块足够大的内存清零以处理画布内容。这可能代价高昂。想想有多少内存可以在高清分辨率下保持RGBA ...这是超过200万像素的数据,大约8 MB的字节数不可否认,这些日子一般都不是 ,但如果有的话任何与推送内存到视频卡有关的带宽或缓存问题,或者你每秒做60次的事情......好吧,期待出现问题。

我经常听到的只是清除以前绘制图像的位置。见http://jsbin.com/olasol/6/edit

我为你做了以下更改。

    for (var i=0; i< noOfDrops; ++i)
    {
        fallingctx.clearRect(
          fallingDrops[i].x-1,
          fallingDrops[i].y-1,
          fallingDrops[i].image.width+2,
          fallingDrops[i].image.height+2);
    }
    for (var i=0; i< noOfDrops; ++i)
    {
        fallingDrops[i].y += fallingDrops[i].speed; //Set the falling speed
        fallingctx.drawImage (fallingDrops[i].image, fallingDrops[i].x, fallingDrops[i].y);
    }

可能有一个很好的理由我需要clearRect 围绕渲染图像,但一个简单的原因让我感到厌烦。 (这与在指定的像素上渲染的东西有关...我完全忘记了。)

你还需要对图像加载之前启动渲染循环的事实做一些事情(也在jsbin中),所以我添加了

var imgSource = "http://lorempixel.com/20/20/sports/"; 
var imgObj = new Image();

并替换superinit

function superinit()
{ 
    imgObj.onload = function(){
        flowerfallsetup();
        requestAnimFrame(flowerfall);
    }
    imgObj.onerror = function (){
        alert("could not load image");
    }
    imgObj.src = imgSource;
}

编辑:由于先前的图片设置,我忘了提及,我确实更改了flowerfallsetup中的行:

      fallingDr["image"] = imgObj; 

有很多方法可以处理图像的异步加载,我只选择了一个对这个例子来说很容易的方法。

编辑:我必须承认,这可能会有更多。它在桌面浏览器上运行良好,但在iPhone上,剪辑问题。如果我能弄清楚导致问题的原因,我会尝试发布更新。