与缓慢处理相比,泄漏并不是因为应用程序使用的系统内存快速增加 .

我通过将文本写入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()命令 .