在画布上绘制10,000个对象javascript [英] draw 10,000 objects on canvas 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.
您建议如何改善效能?
更新:
我尝试分层,但表演恶化
i try layering but the performances worsens
推荐答案
我可以得到你10,000,但有两个主要缺点。
I can get you 10,000 but there are two main drawbacks.
-
您可能会注意到图片不完全尊重透明度,可能修复..但超出了此范围
You may notice the images don't respect transparency entirely, its possible to fix.. but that's beyond the scope of this answer.
您必须使用math来执行任何类型的转换,因为标准画布转换矩阵不能应用于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
即时演示
代码和方法的说明
为了获得最快的性能,可以使用canvas和需要使用 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.
- putImageData
- createImageData
这里还有一个很好的教程,它有点帮助更好地了解。
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 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屋!