与缓慢处理相比,泄漏并不是因为应用程序使用的系统内存快速增加 .
我通过将文本写入2D画布然后为平面网格物体制作纹理来制作“动画公告板” .
由于我希望多个ABB每秒更新多次,我想我会设置一个javascript ABB对象数组,并为每个对象分配画布,上下文,纹理,材质,几何和网格 . 然后,当我更新时,我只需要重绘画布,制作新纹理,将其指定给材质并更新材质 .
这一切都很好,除了随着时间的推移,应用程序 grab 越来越多的内存 . 如果我暂停应用程序(例如切换到另一个选项卡),那么一些处理过程会慢慢处理应用程序使用的内存 . 基本上,新内存采集的速度比内存处理速度快得多 .
这是一个显示效果的jsfiddle .
我一直在尝试各种方法来重新使用旧对象或创建新对象,但似乎没有任何工作 . 请注意,检测到它的主应用程序在R71下运行正常,升级到R77时出现问题 . 我查看了升级说明,但无法查看原因 .
我欢迎任何关于如何解决或避免这个问题的建议 .
以下是一些代码,显示每个ABB的更新方式: -
function SOW_F_grob_BB_Update_a_BB ( thisBB, newText function SOW_F_grob_BB_Update_a_BB ( thisBB, newText )
{
thisBB.params.text = newText;
//var thisCan = thisBB.canvas = document.createElement('canvas');
//var thisCan_Ctx_1 = thisBB.context = thisCan.getContext('2d');
var new_or_old = "new";
if ( new_or_old == "new")
{
//... Getting NEW CANVAS and CONTEXT
var thisCan = document.createElement('canvas');
var thisCan_Ctx_1 = thisCan.getContext('2d');
}
else
{
//... RE-USING OLD CANVAS and CONTEXT trying to solve the memory leak problem.
var thisCan = thisBB.canvas;
var thisCan_Ctx_1 = thisBB.context;
}
thisCan.width = thisBB.params.Pennant_rect_width;//... stretches rectangle
//... ***** BEWARE: Setting the width or height of a <canvas> element
//... will erase its contents
//... and reset all the properties of its drawing context
//... to their default values (http://diveintohtml5.info/canvas.html).
thisCan_Ctx_1.fillStyle = thisBB.params.back_color;
//thisCan_Ctx_1.fillRect(0,0,temp_canvas2.width, temp_canvas2.height);
thisCan_Ctx_1.fillRect(0,0,thisBB.params.Pennant_rect_width, thisBB.params.rect_depth);//... fixed size rectangle, using powers of two
thisCan_Ctx_1.font = thisBB.params.font;
thisCan_Ctx_1.fillStyle = thisBB.params.text_color;
thisCan_Ctx_1.fillText(thisBB.params.text, thisBB.params.text_offset_x, thisBB.params.text_offset_y); //... offset_width, offset_depth of start point of text string (bottom left corner of 1st char).
//... Memory unblocking attempts.
{
//scene.remove( thisBB.mesh );
//thisBB.mesh.material.map.dispose();
//thisBB.mesh.geometry.dispose();
//thisBB.mesh.material.dispose(); //... NOT REQUIRED
//canvas1.parentNode.removeChild(canvas1);
//thisBB.mesh.dispose(); //... not a function, but without this command the old ABBs didn't get removed.
}
//... N.B. texture needs just the name of the source/donor canvas.
var thisNewTexture = thisBB.texture = new THREE.Texture( thisCan );
thisNewTexture.minFilter = THREE.LinearFilter;//THREE.NearestFilter;//... to avoid console warnings about texture .NE. power of two.
thisNewTexture.needsUpdate = true; //... important.
//thisCan_Ctx_1.dispose(); //... not a function, anyway we are keeping them in array.
//thisCan.dispose(); //... not a function, anyway we are keeping them in array.
//thisCan.parentNode.removeChild( thisCan );//... ERROR Uncaught TypeError: Cannot read property 'removeChild' of null
//document.removeElement( thisCan );// ERROR: TypeError: document.removeElement is not a function
//-------------------------------------------------------------------------------------------
//... If plane geometry unchanged then we can just update the material? (maybe).
//var geometry_changed = true;
//... ***** HARD-WIRED ***** , works for now.
var geometry_changed = false;
if ( geometry_changed == true ) //... so must make new mesh and presumably new material.
{
/*
scene.remove( thisBB.mesh );
thisBB.mesh.material.map.dispose();
thisBB.mesh.material.dispose();
thisBB.mesh.geometry.dispose();
thisBB.mesh.dispose();
//... New Material
var thisNewMaterial = thisBB.material = new THREE.MeshBasicMaterial(
{ map: thisNewTexture, side:THREE.DoubleSide } );
thisNewMaterial.transparent = true;
//... New Mesh ( inc. new Geometry).
var thisNewMesh = thisBB.mesh = new THREE.Mesh(
new THREE.PlaneBufferGeometry( thisCan.width, thisCan.height ),
thisNewMaterial
);
//... set mesh position & add to the scene
thisNewMesh.position.set( thisBB.px, thisBB.py, thisBB.pz );
scene.add( thisNewMesh );
*/
}
else //... geometry_changed == false, no need for New Material or New Mesh,
//... just do update because texture and .map have changed.
{
//... Works OK now that we are using the BB array with retained individual textures and materials.
thisBB.mesh.material.map = thisNewTexture; //... no exceptions or warnings
thisBB.mesh.material.map.needsUpdate = true;
} //... if geometry_changed true or false.
thisBB.mesh.position.set( thisBB.params.px, thisBB.params.py, thisBB.params.pz );
}
{
thisBB.params.text = newText;
//var thisCan = thisBB.canvas = document.createElement('canvas');
//var thisCan_Ctx_1 = thisBB.context = thisCan.getContext('2d');
var new_or_old = "new";
if ( new_or_old == "new")
{
//... Getting NEW CANVAS and CONTEXT
var thisCan = document.createElement('canvas');
var thisCan_Ctx_1 = thisCan.getContext('2d');
}
else
{
//... RE-USING OLD CANVAS and CONTEXT trying to solve the memory leak problem.
var thisCan = thisBB.canvas;
var thisCan_Ctx_1 = thisBB.context;
}
thisCan.width = thisBB.params.Pennant_rect_width;//... stretches rectangle
//... ***** BEWARE: Setting the width or height of a <canvas> element
//... will erase its contents
//... and reset all the properties of its drawing context
//... to their default values (http://diveintohtml5.info/canvas.html).
thisCan_Ctx_1.fillStyle = thisBB.params.back_color;
//thisCan_Ctx_1.fillRect(0,0,temp_canvas2.width, temp_canvas2.height);
thisCan_Ctx_1.fillRect(0,0,thisBB.params.Pennant_rect_width, thisBB.params.rect_depth);//... fixed size rectangle, using powers of two
thisCan_Ctx_1.font = thisBB.params.font;
thisCan_Ctx_1.fillStyle = thisBB.params.text_color;
thisCan_Ctx_1.fillText(thisBB.params.text, thisBB.params.text_offset_x, thisBB.params.text_offset_y); //... offset_width, offset_depth of start point of text string (bottom left corner of 1st char).
//... Memory unblocking attempts.
{
//scene.remove( thisBB.mesh );
//thisBB.mesh.material.map.dispose();
//thisBB.mesh.geometry.dispose();
//thisBB.mesh.material.dispose(); //... NOT REQUIRED
//canvas1.parentNode.removeChild(canvas1);
//thisBB.mesh.dispose(); //... not a function, but without this command the old ABBs didn't get removed.
}
//... N.B. texture needs just the name of the source/donor canvas.
var thisNewTexture = thisBB.texture = new THREE.Texture( thisCan );
thisNewTexture.minFilter = THREE.LinearFilter;//THREE.NearestFilter;//... to avoid console warnings about texture .NE. power of two.
thisNewTexture.needsUpdate = true; //... important.
//thisCan_Ctx_1.dispose(); //... not a function, anyway we are keeping them in array.
//thisCan.dispose(); //... not a function, anyway we are keeping them in array.
//thisCan.parentNode.removeChild( thisCan );//... ERROR Uncaught TypeError: Cannot read property 'removeChild' of null
//document.removeElement( thisCan );// ERROR: TypeError: document.removeElement is not a function
//-------------------------------------------------------------------------------------------
//... If plane geometry unchanged then we can just update the material? (maybe).
//var geometry_changed = true;
//... ***** HARD-WIRED ***** , works for now.
var geometry_changed = false;
if ( geometry_changed == true ) //... so must make new mesh and presumably new material.
{
/*
scene.remove( thisBB.mesh );
thisBB.mesh.material.map.dispose();
thisBB.mesh.material.dispose();
thisBB.mesh.geometry.dispose();
thisBB.mesh.dispose();
//... New Material
var thisNewMaterial = thisBB.material = new THREE.MeshBasicMaterial(
{ map: thisNewTexture, side:THREE.DoubleSide } );
thisNewMaterial.transparent = true;
//... New Mesh ( inc. new Geometry).
var thisNewMesh = thisBB.mesh = new THREE.Mesh(
new THREE.PlaneBufferGeometry( thisCan.width, thisCan.height ),
thisNewMaterial
);
//... set mesh position & add to the scene
thisNewMesh.position.set( thisBB.px, thisBB.py, thisBB.pz );
scene.add( thisNewMesh );
*/
}
else //... geometry_changed == false, no need for New Material or New Mesh,
//... just do update because texture and .map have changed.
{
//... Works OK now that we are using the BB array with retained individual textures and materials.
thisBB.mesh.material.map = thisNewTexture; //... no exceptions or warnings
thisBB.mesh.material.map.needsUpdate = true;
} //... if geometry_changed true or false.
thisBB.mesh.position.set( thisBB.params.px, thisBB.params.py, thisBB.params.pz );
}
UPDATE 我发现解决方法是在创建新纹理之前插入命令thisBB.texture.dispose() . 另一种想法(简单地说永远不会使纹理成为thisBB的属性)不起作用 .
这是updated jsfiddle,它允许您切换上面提到的dispose()命令 .