在画布上绘制 10,000 个对象 javascript [英] draw 10,000 objects on canvas javascript

查看:16
本文介绍了在画布上绘制 10,000 个对象 javascript的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

I need draw over 10,000 images (32x32 px) on canvas but over 2000 draws the performances is very bad.

这是一个小例子:

对象结构{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++;
}

使用此代码,我对坐标周围的图像进行了转换.

with this code I traslate the images around of a coordinates.

您有什么建议可以提高性能?

What do you recommend to improve performance?

更新:

我尝试分层,但性能变差

i try layering but the performances worsens

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

推荐答案

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

I can get you 10,000 but there are two main drawbacks.

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

  1. You may notice the images don't respect transparency entirely, its possible to fix.. but that's beyond the scope of this answer.

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

You will have to use math to do any sort of transformations because the standard canvas transformation matrix can not be applied to ImageData

现场演示

代码和方法说明

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

Live Demo

Explanation of the code and methods

So to get the fastest performance possible with canvas and a large number of objects you need to use ImageData. This is accessing the canvas element on a per pixel level basically, and allows you to do all sorts of cool stuff. I used two primary methods.

还有一个不错的教程这会有助于更好地理解.

Also here is a nice tutorial that goes into it a bit to help get a better understanding.

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

So what I did is first I created a temporary canvas for the image

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();
};

Next 是渲染函数中的主要部分

Next Is the main piece which is in the rendering function

我只是发布相关部分.

// 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);

主要的收获是,如果你需要在画布上绘制大量的对象,你不能使用 drawImage,像素操作是你的朋友.

The main Take away from this is, if you need to draw a ridiculous number of objects on the canvas you can't use drawImage, pixel manipulation is your friend.

这篇关于在画布上绘制 10,000 个对象 javascript的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆