优化
This commit is contained in:
@@ -1,9 +1,6 @@
|
||||
<template>
|
||||
<div id="app" class="app">
|
||||
<keep-alive>
|
||||
<router-view :key="$route.name" v-if="$route.meta.keepAlive"/>
|
||||
</keep-alive>
|
||||
<router-view :key="$route.name" v-if="!$route.meta.keepAlive"/>
|
||||
<router-view/>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
|
||||
@@ -40,7 +40,9 @@ export default {
|
||||
viewSize: 20,
|
||||
animationId: null,
|
||||
lastUpdateTime: 0,
|
||||
updateInterval: 100, // 限制更新频率,毫秒
|
||||
updateInterval: 800, // 限制更新频率,毫秒
|
||||
// 标记组件是否已销毁
|
||||
isDestroyed: false
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
@@ -76,19 +78,76 @@ export default {
|
||||
}, 1000);
|
||||
},
|
||||
beforeDestroy () {
|
||||
// 清理资源
|
||||
// 先标记组件已销毁,阻止新消息处理
|
||||
this.isDestroyed = true;
|
||||
// 1. 清理WebSocket(先移除事件监听,再关闭连接)
|
||||
if (this.socket) {
|
||||
this.socket.close();
|
||||
this.socket.onopen = null;
|
||||
this.socket.onmessage = null;
|
||||
this.socket.onclose = null;
|
||||
this.socket.onerror = null;
|
||||
this.socket.close(1000, '组件销毁');
|
||||
this.socket = null;
|
||||
}
|
||||
// 2. 停止动画循环并清理
|
||||
if (this.animationId) {
|
||||
cancelAnimationFrame(this.animationId);
|
||||
this.animationId = null;
|
||||
}
|
||||
// 3. 清理OrbitControls(关键!控制器有内部事件监听)
|
||||
if (this.controls) {
|
||||
this.controls.dispose(); // 控制器自带的清理方法,移除事件监听
|
||||
this.controls = null;
|
||||
}
|
||||
// 4. 清理Three.js场景对象(先从场景移除,再释放资源)
|
||||
if (this.scene) {
|
||||
// 移除点云网格
|
||||
if (this.pointCloudMesh) {
|
||||
this.scene.remove(this.pointCloudMesh);
|
||||
}
|
||||
// 移除小车模型
|
||||
if (this.carMesh) {
|
||||
this.scene.remove(this.carMesh);
|
||||
}
|
||||
// 清空场景(彻底释放所有子对象引用)
|
||||
this.scene.clear();
|
||||
this.scene = null;
|
||||
}
|
||||
// 5. 释放Three.js渲染器及DOM
|
||||
if (this.renderer) {
|
||||
// 从DOM中移除canvas元素(避免残留DOM节点)
|
||||
const container = this.$refs.canvasContainer;
|
||||
if (container && this.renderer.domElement) {
|
||||
container.removeChild(this.renderer.domElement);
|
||||
}
|
||||
// 释放渲染器资源
|
||||
this.renderer.dispose();
|
||||
this.renderer.forceContextLoss(); // 强制释放WebGL上下文(关键!)
|
||||
this.renderer = null;
|
||||
}
|
||||
// 6. 释放几何体和材质(确保先移除引用)
|
||||
if (this.pointCloudGeometry) {
|
||||
this.pointCloudGeometry.dispose();
|
||||
this.pointCloudGeometry = null;
|
||||
}
|
||||
if (this.pointCloudMaterial) {
|
||||
// 先清除材质的纹理引用(避免纹理无法释放)
|
||||
this.pointCloudMaterial.map = null;
|
||||
this.pointCloudMaterial.dispose();
|
||||
this.pointCloudMaterial = null;
|
||||
}
|
||||
// 7. 释放小车纹理(确保材质不再引用)
|
||||
if (this.carTexture) {
|
||||
this.carTexture.dispose();
|
||||
this.carTexture = null;
|
||||
}
|
||||
// 8. 移除窗口大小变化监听(避免重复监听)
|
||||
window.removeEventListener('resize', this.handleResize);
|
||||
// 清理Three.js资源
|
||||
if (this.renderer) this.renderer.dispose();
|
||||
if (this.pointCloudGeometry) this.pointCloudGeometry.dispose();
|
||||
if (this.pointCloudMaterial) this.pointCloudMaterial.dispose();
|
||||
if (this.carTexture) this.carTexture.dispose();
|
||||
// 9. 清空其他引用(帮助GC回收)
|
||||
this.allPoints = [];
|
||||
this.camera = null;
|
||||
this.carMesh = null;
|
||||
this.pointCloudMesh = null;
|
||||
},
|
||||
methods: {
|
||||
/**
|
||||
@@ -130,7 +189,7 @@ export default {
|
||||
*/
|
||||
initControls() {
|
||||
this.controls = new OrbitControls(this.camera, this.renderer.domElement);
|
||||
this.controls.enableRotate = true; // 禁用旋转,保持2D视图
|
||||
this.controls.enableRotate = false; // 禁用旋转,保持2D视图
|
||||
this.controls.enableZoom = true; // 启用缩放
|
||||
this.controls.enablePan = true; // 启用平移(拖动)
|
||||
this.controls.screenSpacePanning = true; // 2D平移模式
|
||||
@@ -245,6 +304,8 @@ export default {
|
||||
};
|
||||
|
||||
this.socket.onmessage = (event) => {
|
||||
// 组件已销毁则直接返回,不处理消息
|
||||
if (this.isDestroyed) return
|
||||
try {
|
||||
// 限制更新频率,优化性能
|
||||
const now = Date.now();
|
||||
@@ -254,7 +315,6 @@ export default {
|
||||
this.lastUpdateTime = now;
|
||||
|
||||
const pointData = JSON.parse(event.data);
|
||||
console.log(pointData.data)
|
||||
this.updatePointCloud(pointData.data);
|
||||
} catch (error) {
|
||||
console.error('解析点云数据失败:', error);
|
||||
@@ -277,6 +337,10 @@ export default {
|
||||
init () {
|
||||
const pointData = points.data
|
||||
this.updatePointCloud(pointData);
|
||||
setTimeout(() => {
|
||||
const arr = [{x: 2, y: 2}, {x: 4, y: 4}]
|
||||
this.updatePointCloud(arr);
|
||||
}, 2000)
|
||||
},
|
||||
|
||||
/**
|
||||
@@ -306,28 +370,46 @@ export default {
|
||||
this.allPoints = [...this.allPoints, ...newUniquePoints];
|
||||
this.pointCount = this.allPoints.length; // 更新总点数
|
||||
|
||||
// 重新创建缓冲区(因数据量变化,需重新分配内存)
|
||||
const pointPositions = new Float32Array(this.pointCount * 3); // x, y, z各占1位
|
||||
this.pointCloudGeometry.setAttribute(
|
||||
'position',
|
||||
new THREE.BufferAttribute(pointPositions, 3)
|
||||
);
|
||||
|
||||
// 获取位置缓冲区并更新数据
|
||||
|
||||
// 动态扩展缓冲区
|
||||
const positionAttribute = this.pointCloudGeometry.getAttribute('position');
|
||||
const positions = positionAttribute.array;
|
||||
|
||||
// 填充数据(z始终为0)
|
||||
for (let i = 0; i < this.pointCount; i++) {
|
||||
const point = this.allPoints[i];
|
||||
// 假设点数据格式为 {x: number, y: number}
|
||||
positions[i * 3] = (point.x || 0) * this.pointScale;
|
||||
positions[i * 3 + 1] = (point.y || 0) * this.pointScale;
|
||||
positions[i * 3 + 2] = 0; // Z轴固定为0
|
||||
let positions;
|
||||
|
||||
if (!positionAttribute) {
|
||||
// 首次初始化:创建缓冲区
|
||||
positions = new Float32Array(this.pointCount * 3);
|
||||
this.pointCloudGeometry.setAttribute(
|
||||
'position',
|
||||
new THREE.BufferAttribute(positions, 3)
|
||||
);
|
||||
} else {
|
||||
// 后续更新:扩展现有缓冲区(避免重建)
|
||||
positions = positionAttribute.array;
|
||||
const newLength = this.pointCount * 3;
|
||||
if (newLength > positions.length) {
|
||||
// 扩展时多预留20%空间,减少频繁扩展
|
||||
const newPositions = new Float32Array(Math.ceil(newLength * 1.2));
|
||||
newPositions.set(positions); // 复制原有数据
|
||||
positions = newPositions;
|
||||
this.pointCloudGeometry.setAttribute(
|
||||
'position',
|
||||
new THREE.BufferAttribute(positions, 3)
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
// 标记属性需要更新
|
||||
positionAttribute.needsUpdate = true;
|
||||
|
||||
// 填充新数据(仅更新新增部分,减少重复计算)
|
||||
const startIndex = (this.pointCount - newUniquePoints.length) * 3; // 从新增点开始
|
||||
for (let i = 0; i < newUniquePoints.length; i++) {
|
||||
const point = newUniquePoints[i];
|
||||
const index = startIndex + i * 3;
|
||||
positions[index] = (point.x || 0) * this.pointScale;
|
||||
positions[index + 1] = (point.y || 0) * this.pointScale;
|
||||
positions[index + 2] = 0;
|
||||
}
|
||||
|
||||
// 标记更新
|
||||
this.pointCloudGeometry.getAttribute('position').needsUpdate = true;
|
||||
},
|
||||
|
||||
/**
|
||||
|
||||
Reference in New Issue
Block a user