gpt4 book ai didi

javascript - Canvas 内存泄漏

转载 作者:行者123 更新时间:2023-11-29 18:14:37 27 4
gpt4 key购买 nike

我试图生成一个带有随机噪声的 Canvas ,但我无法以 60fps 的速度生成整个随机像素的 Canvas ,所以我最终使用内存中的临时 Canvas 来生成一个 64x64 的小图 block ,然后使用上下文填充来重复模式,并让浏览器将这些字节推送到屏幕,而不是使用 javascript 引擎。

速度要快得多,即使在全屏模式下,我也可以在 iOS 设备上获得稳定的 60fps,但我注意到几分钟后 fps 开始下降,直到变得非常慢。

在这个 fiddle 上,我没有使用应限制为 60Hz 的 requestAnimationFrame,而是使用自定义循环,在我的 macbook 上,它以大约 500Hz 开始并迅速减速以强调问题。

http://jsfiddle.net/Victornpb/m42NT/2/

function loop(){
drawNoise();
}


function drawNoise(){
var context = canvas.getContext("2d");
var pattern = context.createPattern(generatePattern(), "repeat");
context.rect(0,0, canvas.width, canvas.height);
context.fillStyle = pattern;
context.fill()
}

//create a on memory canvas to generate a tile with 64x64 pixels of noise and return it
function generatePattern(){

var canvas = document.createElement("canvas");
canvas.width = 64;
canvas.height = 64;
var context = canvas.getContext("2d");

var image = context.getImageData(0, 0, canvas.width, canvas.height);
var imageData = image.data; // here we detach the pixels array from DOM

var p;
var pixels = canvas.width*canvas.height;
while(pixels--){
p = pixels*4;
imageData[p+0] = Math.random() >= 0.5 ? 255 : 0; // Red
imageData[p+1] = Math.random() >= 0.5 ? 255 : 0; // Green
imageData[p+2] = Math.random() >= 0.5 ? 255 : 0; // Blue
imageData[p+3] = 255; // Alpha
}

image.data = imageData;
context.putImageData(image, 0, 0);

return canvas;
}

最佳答案

您在主绘制函数中使用了 context.rect,但没有创建新路径 (beginPath)。所以你所有的 rect 子路径都添加了,并且需要在每一帧上重新绘制 ==>> 很快就太慢了。

==>> 在使用 rect 之前使用 beginPath() 或使用 fillRect。

function drawNoise() {
var context = canvas.getContext("2d");
var pattern = context.createPattern(generatePattern(), "repeat");
context.fillStyle = pattern;
context.fillRect(0, 0, canvas.width, canvas.height);
}

请注意,您可以通过创建 Canvas 并在每次调用 generatePattern 时创建图像数据来赢得大量时间,而是一次又一次地重复使用相同的 imageData。 更重要的是,你只能设置一次 alpha :

//create a on memory canvas to generate a tile with 64x64 pixels of noise and return it
var generatePattern = (function () {
var canvas = document.createElement("canvas");
canvas.width = 64;
canvas.height = 64;
var context = canvas.getContext("2d");
var image = context.getImageData(0, 0, canvas.width, canvas.height);
var imageData = image.data; // here we detach the pixels array from DOM
// set the alpha only once.
var p = 0,
pixels = canvas.width * canvas.height;
while (pixels--) {
imageData[p + 3] = 255; // Alpha
p += 4;
}
var _generatePattern = function () {
var p = 0;
var pixels = canvas.width * canvas.height;
var data = imageData;
var rnd = Math.random;
while (pixels--) {
data[p++ ] = rnd() >= 0.5 ? 255 : 0; // Red
data[p++ ] = rnd() >= 0.5 ? 255 : 0; // Green
data[p++ ] = rnd() >= 0.5 ? 255 : 0; // Blue
p++;
}
context.putImageData(image, 0, 0);
return canvas;
}
return _generatePattern;
})();

更新的 fiddle 在这里:

http://jsfiddle.net/gamealchemist/m42NT/15/

编辑:使用一次调用 random() 只是为了获得一个随机位是一种矫枉过正:使用 math.random() 获得一个位域,然后在该位域为空时重新填充它。这里我从 Math.random() 中取出了 21 位,因为它没有更多的有效位。这样,对于相同的结果,您对该函数 (!!) 的调用减少了 21 倍。

http://jsfiddle.net/gamealchemist/m42NT/18/

//create a on memory canvas to generate a tile with 64x64 pixels of noise and return it
var generatePattern = (function () {
var canvas = document.createElement("canvas");
canvas.width = 64;
canvas.height = 64;
var context = canvas.getContext("2d");
var image = context.getImageData(0, 0, canvas.width, canvas.height);
var imageData = image.data; // here we detach the pixels array from DOM
// set the alpha only once.
var p = 0,
pixels = canvas.width * canvas.height;
while (pixels--) {
imageData[p + 3] = 255; // Alpha
p += 4;
}
var _generatePattern = function () {
var p = 0;
var pixels = canvas.width * canvas.height;
var data = imageData;
var rnd = Math.random;
var bitsLeft = 0;
var multiplier = (1<<22)-1;
var mask = 0;
while (pixels--) {
if (!bitsLeft) {
bitsLeft=21;
mask= 0 | (Math.random()*multiplier);
}
data[p++ ] = (mask & 1) && 255 ; // Red
data[p++ ] = (mask & 2 ) && 255 ; // Green
data[p++ ] = (mask & 4) && 255; // Blue
p++;
mask>>=3;
bitsLeft-=3;
}
context.putImageData(image, 0, 0);
return canvas;
}
return _generatePattern;
})();

关于javascript - Canvas 内存泄漏,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/24445877/

27 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com