Преглед на файлове

[Fix 0000] 注氮机地上地下模型可能出现的详情框问题修复

houzekong преди 2 дни
родител
ревизия
ddc3f348d5

+ 28 - 19
src/views/vent/monitorManager/compressor/nitrogen.dishang.threejs.ts

@@ -126,31 +126,40 @@ class NitrogenOverground {
     if (this.nitrogenNum > 0) {
       for (let i = 0; i < this.nitrogenNum; i++) {
         const nitrogenModal = this.group.getObjectByName('nitrogenModal' + i) as THREE.Object3D;
-        if (nitrogenModal && !nitrogenModal.getObjectByName('monitorNitrogenText')) {
-          const element = document.getElementById('nitrogenMonitor' + (i + 1)) as HTMLElement;
-          if (element) {
-            const nitrogenMonitorCSS3D = new CSS3DSprite(element);
-            nitrogenMonitorCSS3D.name = 'monitorNitrogenText' + i;
-            nitrogenMonitorCSS3D.scale.set(0.003, 0.003, 0.003);
-            if (i == 0) nitrogenMonitorCSS3D.position.set(-0.89, 0.31, 0);
-            if (i == 1) nitrogenMonitorCSS3D.position.set(-0.89, 0.31, 0.04);
-            if (i == 2) nitrogenMonitorCSS3D.position.set(-0.89, 0.31, 0.08);
-            if (i == 3) nitrogenMonitorCSS3D.position.set(-0.89, 0.31, 0.12);
-            nitrogenModal.add(nitrogenMonitorCSS3D);
-          }
+        if (!nitrogenModal) continue;
+        const name = 'monitorNitrogenText' + i;
+        const element = document.getElementById('nitrogenMonitor' + (i + 1)) as HTMLElement;
+        let sprite = nitrogenModal.getObjectByName(name) as CSS3DSprite | undefined;
+        // 已挂过就复用(原守卫的名字少了序号,导致每次 addCssText 都重复挂一批精灵);
+        // 节点被 Vue 重建过则换成挂到当前节点,旧节点已是孤儿可安全移除
+        if (sprite && element && sprite.element !== element) {
+          sprite.removeFromParent();
+          sprite = undefined;
         }
+        if (sprite) {
+          sprite.visible = true;
+          continue;
+        }
+        if (!element) continue;
+        sprite = new CSS3DSprite(element);
+        sprite.name = name;
+        sprite.scale.set(0.003, 0.003, 0.003);
+        if (i == 0) sprite.position.set(-0.89, 0.31, 0);
+        if (i == 1) sprite.position.set(-0.89, 0.31, 0.04);
+        if (i == 2) sprite.position.set(-0.89, 0.31, 0.08);
+        if (i == 3) sprite.position.set(-0.89, 0.31, 0.12);
+        nitrogenModal.add(sprite);
       }
     }
   };
 
   clearCssText = () => {
-    if (this.nitrogenNum > 0) {
-      for (let i = 0; i < this.nitrogenNum; i++) {
-        const nitrogenModal = this.group.getObjectByName('nitrogenModal' + i) as THREE.Object3D;
-        if (nitrogenModal && nitrogenModal.getObjectByName('monitorNitrogenText')) {
-          nitrogenModal.remove(nitrogenModal.getObjectByName('monitorNitrogenText') as THREE.Object3D);
-        }
-      }
+    // 只隐藏、不移除:CSS3DObject 被移除时会把它手里的 DOM 元素一并从文档删掉,之后再 addCssText 就取不到元素
+    if (this.nitrogenNum <= 0) return;
+    for (let i = 0; i < this.nitrogenNum; i++) {
+      const nitrogenModal = this.group.getObjectByName('nitrogenModal' + i) as THREE.Object3D;
+      const sprite = nitrogenModal?.getObjectByName('monitorNitrogenText' + i);
+      if (sprite) (sprite as THREE.Object3D).visible = false;
     }
   };
 

+ 35 - 29
src/views/vent/monitorManager/compressor/nitrogen.dixia.threejs.ts

@@ -227,45 +227,51 @@ class NitrogenUnderground {
     }
     if (this.nitrogenNum > 0) {
       for (let i = 0; i < 2; i++) {
-        if (this.group && !this.group.getObjectByName('monitorNitrogenText' + i)) {
-          const element = document.getElementById('nitrogenMonitor' + (i + 1)) as HTMLElement;
-          if (element) {
-            const nitrogenMonitorCSS3D = new CSS3DSprite(element);
-            nitrogenMonitorCSS3D.name = 'monitorNitrogenText' + i;
-            nitrogenMonitorCSS3D.scale.set(0.005, 0.005, 0.005);
-            if (i == 0) nitrogenMonitorCSS3D.position.set(-0.89, 0.31, 0);
-            if (i == 1) nitrogenMonitorCSS3D.position.set(1.44, 0.31, 0.04);
-            // if (i == 2) nitrogenMonitorCSS3D.position.set(-0.89, 0.31, 0.08);
-            // if (i == 3) nitrogenMonitorCSS3D.position.set(-0.89, 0.31, 0.12);
-            this.group.add(nitrogenMonitorCSS3D);
-          }
+        const element = document.getElementById('nitrogenMonitor' + (i + 1)) as HTMLElement;
+        let sprite = this.group?.getObjectByName('monitorNitrogenText' + i) as CSS3DSprite | undefined;
+        // 节点被 Vue 重建过(机数变化时 v-for 增删)→ 换成挂到当前节点;旧节点已是孤儿,可以安全移除
+        if (sprite && element && sprite.element !== element) {
+          sprite.removeFromParent();
+          sprite = undefined;
         }
-        // 而如若此项超出了已绑定的注氮机数量,则隐藏或销毁
-        if (this.group && i >= this.nitrogenNum && this.group.getObjectByName('monitorNitrogenText' + i)) {
-          this.group.remove(this.group.getObjectByName('monitorNitrogenText' + i) as THREE.Object3D);
+        if (!sprite && element) {
+          sprite = new CSS3DSprite(element);
+          sprite.name = 'monitorNitrogenText' + i;
+          sprite.scale.set(0.005, 0.005, 0.005);
+          if (i == 0) sprite.position.set(-0.89, 0.31, 0);
+          if (i == 1) sprite.position.set(1.44, 0.31, 0.04);
+          this.group.add(sprite);
         }
+        // 超出已绑定机数的槽位置为不可见(不能销毁:CSS3DObject 一被移除会连带把 DOM 元素删掉,之后再也挂不回来)
+        if (sprite) sprite.visible = i < this.nitrogenNum;
       }
     }
-    if (this.group && !this.group.getObjectByName('downWindMonitor')) {
+    if (this.group) {
       const element = document.getElementById('downWindMonitor') as HTMLElement;
-      if (element) {
-        const downWindMonitorCSS3D = new CSS3DSprite(element);
-        downWindMonitorCSS3D.name = 'downWindMonitor';
-        downWindMonitorCSS3D.scale.set(0.005, 0.005, 0.005);
-        downWindMonitorCSS3D.position.set(-2.95, 0.57, 0);
-        this.group.add(downWindMonitorCSS3D);
+      let downWindMonitor = this.group.getObjectByName('downWindMonitor') as CSS3DSprite | undefined;
+      // 与机位框同样处理:节点被 Vue 重建过就换成挂到当前节点(旧节点是孤儿,可安全移除)
+      if (downWindMonitor && element && downWindMonitor.element !== element) {
+        downWindMonitor.removeFromParent();
+        downWindMonitor = undefined;
+      }
+      if (!downWindMonitor && element) {
+        downWindMonitor = new CSS3DSprite(element);
+        downWindMonitor.name = 'downWindMonitor';
+        downWindMonitor.scale.set(0.005, 0.005, 0.005);
+        downWindMonitor.position.set(-2.95, 0.57, 0);
+        this.group.add(downWindMonitor);
       }
+      // 无机数时不显示下风侧框(CSS3D 渲染器会把已接管对象的 display 强制置空,隐藏要用 visible)
+      if (downWindMonitor) downWindMonitor.visible = this.nitrogenNum > 0;
     }
   };
 
   clearCssText = () => {
-    if (this.nitrogenNum > 0) {
-      for (let i = 0; i < 2; i++) {
-        const mesh = this.group.getObjectByName('monitorNitrogenText' + i);
-        if (this.group && mesh) {
-          this.group.remove(mesh);
-        }
-      }
+    // 只隐藏、不移除:CSS3DObject 被移除时会把它手里的 DOM 元素一并从文档删掉,之后再 addCssText 就取不到元素
+    if (this.nitrogenNum <= 0) return;
+    for (let i = 0; i < 2; i++) {
+      const sprite = this.group.getObjectByName('monitorNitrogenText' + i);
+      if (sprite) (sprite as THREE.Object3D).visible = false;
     }
   };