fix: 效果图页切Tab后3D空白(v-show隐藏下0尺寸初始化+NaN投影矩阵), 增加ResizeObserver容器尺寸追踪与零尺寸保护

This commit is contained in:
HHY
2026-10-05 06:23:18 -07:00
parent 40ced77733
commit cbc96dd166
2 changed files with 11 additions and 2 deletions
+10 -2
View File
@@ -54,6 +54,8 @@
* - 视角预设 / 自动旋转 / 截图导出
*/
import { onMounted, onBeforeUnmount, ref, watch } from 'vue'
let ro: ResizeObserver | null = null
import { ElMessage } from 'element-plus'
import * as THREE from 'three'
import {
@@ -475,6 +477,8 @@ function loop() {
function onResize() {
const wrap = wrapRef.value, cv = cvRef.value
if (!wrap || !cv || !renderer || !camera) return
// 容器不可见(display:none)时尺寸为 0,跳过避免 NaN 投影矩阵
if (!wrap.clientWidth || !wrap.clientHeight) return
renderer.setSize(wrap.clientWidth, wrap.clientHeight)
camera.aspect = wrap.clientWidth / wrap.clientHeight
camera.updateProjectionMatrix()
@@ -512,15 +516,18 @@ function screenshot() {
onMounted(() => {
const wrap = wrapRef.value!, cv = cvRef.value!
renderer = new THREE.WebGLRenderer({ canvas: cv, antialias: true, preserveDrawingBuffer: true })
renderer.setSize(wrap.clientWidth, wrap.clientHeight)
renderer.setSize(wrap.clientWidth || 1, wrap.clientHeight || 1)
renderer.shadowMap.enabled = true
camera = new THREE.PerspectiveCamera(50, wrap.clientWidth / wrap.clientHeight, 0.01, 100)
camera = new THREE.PerspectiveCamera(50, (wrap.clientWidth || 1) / (wrap.clientHeight || 1), 0.01, 100)
cv.addEventListener('mousedown', onDown)
window.addEventListener('mousemove', onMove)
window.addEventListener('mouseup', onUp)
cv.addEventListener('wheel', e => { e.preventDefault(); onWheel(e) }, { passive: false })
cv.addEventListener('contextmenu', e => e.preventDefault())
window.addEventListener('resize', onResize)
// 容器尺寸追踪:v-show 隐藏下挂载(如效果图页切 Tab)时初始尺寸为 0,显示瞬间自动恢复
ro = new ResizeObserver(onResize)
ro.observe(wrap)
watch(() => props.drawingData, () => {
try {
if (props.drawingData) build(parseDrawing(props.drawingData))
@@ -535,6 +542,7 @@ onMounted(() => {
onBeforeUnmount(() => {
cancelAnimationFrame(raf)
dispose()
ro?.disconnect()
window.removeEventListener('resize', onResize)
renderer?.dispose()
})