• vue3结合three.js 展示3d模型时, 从a路由跳转到b路由,浏览器后退到a路由时,模型加载完后一片空白,并且自定义的CSS2DObject 标签 重复出现


    • 问题发现

    这个问题是打包之后,上线到服务器上发现的,开发过程中却没有遇到,发现这个问题后,在开发模式下,去各种路由跳转然后回去也没有出现这个问题。说明这个问题只有打包后才会出现的!

    问题这里展开说一下,标题只阐述了部分,问题罗列出来就是路由a跳转到b,再回到a时,模型加载空白, 并且自定义的css2dobject 标签会重复,并且重复a路由跳转b,再回去a, 页面就会变得很卡。多重复几次页面会卡死。 

    • 问题解决

    大概花了半天时间去百度查阅资料,找到了问题的解决方案的一半【但是这个确实一个很棒的方案,某些时候你的问题可能就只需要一半】:

    Three.js 内存释放问题_threejs在vue中内存泄露

    为什么说是一半呢,确实通过这个老哥写的方法,内存问题得到了解决,a路由跳转到b路由,再回到的a,页面确实不卡了, 但是模型加载还是有问题,自定义的2d标签重复出现问题确实解决了。

    首先是 通过控制台审查元素, 发现渲染3d容器下有两个canvas标签,由于离开a路由时没有把canvas给销毁掉,导致回到a路由时重新渲染的3d canvas 被第一次的挤到下方去,导致看不见【容器设置了 overflo: hidden】

    所以另一半解决方案就是 再组件取消挂载前,把这个canvas给移除掉:

    onBeforeUnmount(() => { // 组件移除之前触发
    	try {
        document.querySelector('.pro3d-main').innerHTML = ''; // 3d容器,下面挂载着 canvas 容器,这里直接清空3d容器子元素
    		scene.clear(); // 移除scene
    		rt && rt.dispose() // 
            【rt 来源:import ResourceTracker  from '@/data/dispose.js' 
    
                      const rt = new ResourceTracker();
                      const track = rt.track.bind(rt);】
    		renderer.value.dispose();
    		renderer.value.forceContextLoss();
    		renderer.value.content = null;
        
    		cancelAnimationFrame(render)
    		console.log(renderer.value.info)   //查看memery字段  都为0
            console.log(scene) //  查看scene ,children为空数组,表示 模型等销毁ok
    	}catch (e) {
    		console.log(e)
    	}
    })
    
    // dispose.js
    import * as THREE from 'three'
    export default class ResourceTracker {
       constructor() {
       	this.resources = new Set();
       }
       track(resource) {
       	if (!resource) {
       		return resource;
       	}
    
       	// handle children and when material is an array of materials or
       	// uniform is array of textures
       	if (Array.isArray(resource)) {
       		resource.forEach(resource => this.track(resource));
       		return resource;
       	}
    
       	if (resource.dispose || resource instanceof THREE.Object3D) {
       		this.resources.add(resource);
       	}
       	if (resource instanceof THREE.Object3D) {
       		this.track(resource.geometry);
       		this.track(resource.material);
       		this.track(resource.children);
       	} else if (resource instanceof THREE.Material) {
       		// We have to check if there are any textures on the material
       		for (const value of Object.values(resource)) {
       			if (value instanceof THREE.Texture) {
       				this.track(value);
       			}
       		}
       		// We also have to check if any uniforms reference textures or arrays of textures
       		if (resource.uniforms) {
       			for (const value of Object.values(resource.uniforms)) {
       				if (value) {
       					const uniformValue = value.value;
       					if (uniformValue instanceof THREE.Texture ||
       						Array.isArray(uniformValue)) {
       						this.track(uniformValue);
       					}
       				}
       			}
       		}
       	}
       	return resource;
       }
       untrack(resource) {
       	this.resources.delete(resource);
       }
       dispose() {
       	for (const resource of this.resources) {
       		if (resource instanceof THREE.Object3D) {
       			if (resource.parent) {
       				resource.parent.remove(resource);
       			}
       		}
       		if (resource.dispose) {
       			resource.dispose();
       		}
       	}
       	this.resources.clear();
       }
    }
  • 相关阅读:
    python 面向对象专题(二):类的空间问题、类与对象之间的关系、类与类之间的关系
    python 面向对象专题(一):面向对象初识、面向对象结构、类、self、实例化对象
    数据可视化之PowerQuery篇(二十)如何计算在职员工数量?
    数据可视化之PowerQuery篇(十九)PowerBI数据分析实践第三弹 | 趋势分析法
    数据可视化之PowerQuery篇(十八)Power BI数据分析应用:结构百分比分析法
    数据可视化之PowerQuery篇(十七)Power BI数据分析应用:水平分析法
    ccoshf (Numerics) – C 中文开发手册
    HTML DOM removeAttribute() 方法
    curses.panel (Operating System) – Python 中文开发手册
    在Java中使用预定义的类名作为类或变量名称
  • 原文地址:https://www.cnblogs.com/Hijacku/p/15927784.html
Copyright © 2020-2023  润新知