- 問題發現
這個問題是打包之后,上線到服務器上發現的,開發過程中卻沒有遇到,發現這個問題后,在開發模式下,去各種路由跳轉然后回去也沒有出現這個問題。說明這個問題只有打包后才會出現的!
問題這里展開說一下,標題只闡述了部分,問題羅列出來就是路由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();
}
}
