- 问题发现
这个问题是打包之后,上线到服务器上发现的,开发过程中却没有遇到,发现这个问题后,在开发模式下,去各种路由跳转然后回去也没有出现这个问题。说明这个问题只有打包后才会出现的!
问题这里展开说一下,标题只阐述了部分,问题罗列出来就是路由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();
}
}