8

我一直在尝试为我正在创建的 javascript 游戏制作一些视觉效果,我注意到我用来调节精灵颜色的一段代码使我的浏览器内存使用量不断增加,看似没有限制。

您可以在此处查看代码和内存泄漏:http: //timzook.tk/javascript/test.html

这种内存泄漏仅发生在我的 updateimage() 函数中,当我每帧(通过 setInterval)从画布上下文中调用 getImageData 以使新的 ImageData 对象重新着色时。我原以为javascript的垃圾收集器会破坏旧的垃圾收集器,但如果不是,我不知道如何手动销毁它。任何帮助弄清楚它为什么这样做或如何解决它将不胜感激。

我的问题与这个问题非常相似:What is leaking memory with this use of getImageData, javascript, HTML5 canvas但是,我需要我的代码来运行 setInterval 调用的函数中的每一帧,他将其移出 setInterval 函数的解决方案是这对我来说不是一个选择,我不能发表评论询问他是否找到了其他解决方法。

测试人员请注意:由于此示例使用 getImageData,因此无法仅通过将其放入 .html 文件中进行本地测试,因此需要 Web 服务器。此外,它显然使用 HTML5 元素,因此某些浏览器无法使用它。

编辑:*已解决* 谢谢,下面的解决方案修复了它。我没有意识到你可以像在 drawImage() 中使用图像一样使用画布元素,我重组了我的代码,因此它现在使用的内存显着减少。如果有人想查看,我将此更改后的代码上传到上面链接的页面。

4

1 回答 1

12

您的调用不会导致内存泄漏getImageData()。您的问题的根源是这一行:

TempImg.src = ImgCanvas.toDataURL("image/png");

实际上,每次执行该行代码时,浏览器都会“下载”另一个图像并将其存储在内存中。所以,你最终得到的是一个增长非常快的缓存。您可以通过在 Chrome 中打开该站点并检查开发人员工具 ( ctrl+shift+i) 的资源选项卡来轻松验证这一点。

您可以通过在该画布上创建并存储图像数据来解决此问题,而不是在每次调用循环TempImgCanvas后更新图像对象。updateimage()

我必须离开一段时间,但如果你愿意,我可以在几个小时内回来后做一个例子。


编辑:我对事物进行了一些重组并消除了您的缓存问题。您只需要进行两项更改。第一个是用updateimage()这个替换你的函数:

function updateimage() {    
    var TempImgData = ImgContext.getImageData(0, 0, ImgCanvas.width, ImgCanvas.height);
    var NewData = TempImgData.data;
    var OrigData = ImgData.data;

    //Change image color
    var len = 4*ImgData.width*ImgData.height-1;
    for(var i=0;i<=len;i+=4) {
        NewData[i+0] = OrigData[i+0] * color.r;
        NewData[i+1] = OrigData[i+1] * color.g;
        NewData[i+2] = OrigData[i+2] * color.b;
        NewData[i+3] = OrigData[i+3];
    }

    //Put changed image onto the canvas
    ImgContext.putImageData(TempImgData, 0, 0);
}

第二个是将最后一行更新draw()为如下所示:

drawImg(ImgCanvas, Positions[i].x, Positions[i].y, Positions[i].x+Positions[i].y);

使用此更新后的代码,我们只需参考原始基础(白色)图像数据,并在每次执行该updateimage()函数时根据该数据计算新值。当您打电话时,getImageData()您会收到画布上图像数据的副本,因此如果您编辑画布或数据,另一个保持不变。您已经开始获取原始基础图像数据,因此使用它而不是每次更新时都必须重新获取它是有意义的。

此外,您会注意到我修改了您的循环,稍微改变了图像颜色。通过获取您想要访问/修改的实际数据数组的句柄,您不必在每次循环时都从父对象解析数组位置。这种技术实际上会带来相当不错的性能提升。你的表现一开始就很好,但提高效率也无妨,因为它非常简单。

于 2011-10-03T20:37:30.923 回答