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();
   }
}

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM