在画布上绘制10,000个对象javascript

J26*_*261 17 javascript performance html5 canvas drawimage

我需要在画布上绘制超过10,000张图像(32x32像素),但超过2000画的表现非常糟糕.

这是一个小例子:

对象结构 {position:0}

for(var nObject = 0; nObject < objects.length; nObject++){
    ctx.save();
    ctx.translate(coords.x,coords.y);
    ctx.rotate(objects[nObject].position/100);
    ctx.translate(radio,0);
    ctx.drawImage(img,0,0);
    ctx.restore();
    objects[nObject].position++;
}
Run Code Online (Sandbox Code Playgroud)

使用这段代码我可以对坐标周围的图像进行扫描.

您建议什么来提高性能?

更新:

我尝试分层,但表现恶化

http://jsfiddle.net/72nCX/3/

Lok*_*tar 50

我可以给你10,000,但有两个主要的缺点.

  1. 您可能会注意到图像完全不尊重透明度,可以修复..但这超出了本答案的范围.

  2. 您将不得不使用数学进行任何类型的转换,因为标准画布转换矩阵无法应用于ImageData

现场演示

代码和方法的说明

因此,要使用canvas和大量对象获得最快的性能,您需要使用ImageData.这基本上是在每像素级别访问canvas元素,并允许你做各种很酷的东西.我使用了两种主要方法.

这里还有一个很好的教程,有助于更好地理解它.

所以我做的是首先我为图像创建了一个临时画布

imgToDraw.onload = function () {
    // In memory canvas
    imageCanvas = document.createElement("canvas"),
    iCtx = imageCanvas.getContext("2d");

    // set the canvas to the size of the image
    imageCanvas.width = this.width;
    imageCanvas.height = this.height;

    // draw the image onto the canvas
    iCtx.drawImage(this, 0, 0);

    // get the ImageData for the image.
    imageData = iCtx.getImageData(0, 0, this.width, this.height);
    // get the pixel component data from the image Data.
    imagePixData = imageData.data;

    // store our width and height so we can reference it faster.
    imgWidth = this.width;
    imgHeight = this.height;

    draw();
};
Run Code Online (Sandbox Code Playgroud)

Next是渲染功能中的主要部分

我只是张贴相关部分.

// create new Image data. Doing this everytime gets rid of our 
// need to manually clear the canvas since the data is fresh each time
var canvasData = ctx.createImageData(canvas.width, canvas.height),
    // get the pixel data
    cData = canvasData.data;

// Iterate over the image we stored 
for (var w = 0; w < imgWidth; w++) {
    for (var h = 0; h < imgHeight; h++) {
        // make sure the edges of the image are still inside the canvas
        // This also is VERY important for perf reasons
        // you never want to draw outside of the canvas bounds with this method
        if (entity.x + w < width && entity.x + w > 0 &&
            entity.y + h > 0 && entity.y + h < height) {

            // get the position pixel from the image canvas
            var iData = (h * imgWidth + w) * 4;

            // get the position of the data we will write to on our main canvas
            // the values must be whole numbers ~~ is just Math.floor basically
            var pData = (~~ (entity.x + w) + ~~ (entity.y + h) * width) * 4;

            // copy the r/g/b/ and alpha values to our main canvas from 
            // our image canvas data.

            cData[pData] = imagePixData[iData];
            cData[pData + 1] = imagePixData[iData + 1];
            cData[pData + 2] = imagePixData[iData + 2];
            // this is where alpha blending could be applied
            if(cData[pData + 3] < 100){
                cData[pData + 3] = imagePixData[iData + 3];
            }
        }
    }
}

// now put all of that image data we just wrote onto the actual canvas.
ctx.putImageData(canvasData, 0, 0);
Run Code Online (Sandbox Code Playgroud)

主要的是,如果您需要在画布上绘制一些无法使用的荒谬物体drawImage,像素操作就是您的朋友.

  • 此外,代码受内存限制,因此不是将四个浮点值放在 JS 对象中,而是将所有数据放在 Float64Array 中。把它们放在一起,你可以(在我的笔记本电脑中)将精灵的 nr 增加到 50000,并且仍然更快:http://jsfiddle.net/vanderZwan/ddg1kpfr/1/ (2认同)