可怕的Canvas GetImageData()/ PutImageData()在移动设备上的表现

Dan*_*ola 8 javascript performance html5 canvas getimagedata

我正在做一些HTML5游戏,并且在地图开头加载我的精灵时,我使用GetImageData()/循环遍历所有图像/ PutImageData().

这在我的电脑上运行得非常好,然而,在我的手机上,它的速度非常慢.

PC: 5-6 ms
iPhone 4: 300-600 ms
Android HTC Desire S: 2500-3000 ms
Run Code Online (Sandbox Code Playgroud)

我一直在做一些非常基本的基准测试,并且GetImageData和PutImageData都运行得非常快,需要很长时间的是循环内容.

现在,我显然希望手机放慢速度,但1000x听起来有点过分,加载大约需要4分钟,因此我的HTC无法正常工作.此外,游戏中的其他所有内容都以非常合理的速度运行(主要是因为屏幕更小,但仍然,它在手机上的JS工作得非常好)


我在这个处理中所做的基本上是将精灵"变暗"到一定程度.我只是循环遍历所有像素,并将它们乘以值<1.这就是全部.

因为这太慢了......使用Canvas功能(合成,不透明等等)是否有更好的方法来做同样的事情,而不是逐个遍历所有像素?

注意:此图层具有一些100%透明像素,以及一些100%不透明像素.两者都需要保持100%不透明或100%透明.

我想到的事情是行不通的:
1)用新的画布绘制精灵,不透明度较低.这不起作用,因为我需要精灵保持不透明,只是更暗.
2)绘制精灵,并在它们上面画一个半透明的黑色矩形.这会让它们变暗,但它也会使我的透明像素不再透明......

有任何想法吗?

这是我正在使用的代码,以防万一你看到一些非常愚蠢的东西:

function DarkenCanvas(baseImage, ratio) {
    var tmpCanvas = document.createElement("canvas");
    tmpCanvas.width = baseImage.width;
    tmpCanvas.height = baseImage.height;
    var ctx = tmpCanvas.getContext("2d");
    ctx.drawImage(baseImage, 0, 0);

    var pixelData = ctx.getImageData(0, 0, tmpCanvas.width, tmpCanvas.height);
    var length = pixelData.data.length;
    for (var i = 0; i < length; i+= 4) {
        pixelData.data[i] = pixelData.data[i] * ratio;
        pixelData.data[i + 1] = pixelData.data[i + 1] * ratio;
        pixelData.data[i + 2] = pixelData.data[i + 2] * ratio;
    }

    ctx.putImageData(pixelData, 0, 0);
    return tmpCanvas
}
Run Code Online (Sandbox Code Playgroud)

编辑:这是我正在尝试用图像做的一个例子:
原文:http:
//www.crystalgears.com/isoengine/sprites-ground.png Darkened:http://www.crystalgears.com/isoengine /sprites-ground_darkened.png

谢谢!
丹尼尔

Sim*_*ris 11

Phrogz有正确的想法.你真的只想用'source-atop'globalCompositeOperation在整个事物上画一个半透明(或比率透明)的黑色.

像这样:http://jsfiddle.net/F4cNg/

实际上有一个很好的问题,像这样复杂的变暗,但作者删除它是一个真正的耻辱.即使是复杂的形状,也可以在绘制的东西上制作黑暗面具.它们可能对你没有帮助,但是为了完整性以及任何寻找"变暗画布"的东西,其中某些部分保持光亮(禁区),可以使用'xor'globalCompositeOperation来完成,如下所示:

http://jsfiddle.net/k6Xwy/1/


小智 10

您是否看过这个性能提示?:http: //ajaxian.com/archives/canvas-image-data-optimization-tip

他们谈论减少对DOM的调用以提高性能.

因此,基于此提示,您可以尝试:

var pixel = ctx.getImageData(0, 0, tmpCanvas.width, tmpCanvas.height);
    pixelData=pixel.data; // detach the pixel array from DOM
    var length = pixelData.length;
    for (var i = 0; i < length; i+= 4) {
        pixelData[i] = pixelData[i] * ratio;
        pixelData[i + 1] = pixelData[i + 1] * ratio;
        pixelData[i + 2] = pixelData[i + 2] * ratio;
    }
Run Code Online (Sandbox Code Playgroud)

你的.data电话可能会减慢你的速度.