hongrunxia 5 giorni fa
parent
commit
97e9a10b08

BIN
public/dwg/Microsoft_YaHei.ttf


File diff suppressed because it is too large
+ 0 - 0
public/dwg/Microsoft_YaHei_Regular.typeface.json


BIN
public/dwg/arial.ttf


File diff suppressed because it is too large
+ 0 - 0
public/dwg/helvetiker_regular.typeface.json


BIN
public/dwg/hztxt.shx


BIN
public/dwg/simplex.shx


BIN
public/texture/safetymonitor3D.png


+ 79 - 3
src/views/vent/cad/dwgViewer.vue

@@ -66,6 +66,8 @@
 <script setup lang="ts">
   import { ref, onMounted, onUnmounted, reactive } from 'vue';
   import { Viewer2d, ViewerEvent, CoordinateUtils, THREE } from '@x-viewer/core';
+  import { CSS3DRenderer, CSS3DObject } from 'three/examples/jsm/renderers/CSS3DRenderer.js';
+  import { CSS2DObject } from 'three/examples/jsm/renderers/CSS2DRenderer.js';
   import { useAppStoreWithOut } from '/@/store/modules/app';
   import dayjs from 'dayjs';
 
@@ -83,6 +85,13 @@
 
   const containerId = 'dwg-viewer-canvas';
   const dwgSrc = '/dwg/2026年2月总平面布置图_无高程.dwg';
+  const fontFiles = [
+    '/dwg/simplex.shx',
+    '/dwg/hztxt.shx',
+    '/dwg/arial.ttf',
+    '/dwg/Microsoft_YaHei.ttf',
+    '/dwg/Microsoft_YaHei_Regular.typeface.json',
+  ];
   let markerIdCounter = 0;
 
   // ==================== 表格 ====================
@@ -141,8 +150,20 @@
   const currentCoord = reactive({ x: 0, y: 0, z: 0 });
 
   // 存储 marker:markerId → { deviceId, worldPos, domEl }
-  const markersMap = new Map<string, { deviceId: string; worldPos: { x: number; y: number }; mesh: THREE.Mesh }>();
+  const markersMap = new Map<
+    string,
+    {
+      deviceId: string;
+      worldPos: { x: number; y: number };
+      mesh: THREE.Mesh;
+      iconSprite: THREE.Sprite;
+      cssLabel: CSS2DObject;
+    }
+  >();
   const allMeshes: THREE.Mesh[] = [];
+  const allIconSprites: THREE.Sprite[] = [];
+  const allCssLabels: CSS2DObject[] = [];
+  const textureLoader = new THREE.TextureLoader();
 
   const monitoringData = ref<ReturnType<typeof getMockMonitoring> | null>(null);
   const modalVisible = ref(false);
@@ -230,7 +251,38 @@
     viewer.scene.add(mesh);
     allMeshes.push(mesh);
 
-    markersMap.set(markerId, { deviceId: device.id, worldPos: { x: location.x, y: location.y }, mesh });
+    // 精灵图标(safetymonitor3D.png)
+    const tex = textureLoader.load('/texture/safetymonitor3D.png');
+    const spriteMat = new THREE.SpriteMaterial({ map: tex, depthTest: false, depthWrite: false, transparent: true });
+    const icon = new THREE.Sprite(spriteMat);
+    icon.position.set(location.x, location.y, 0);
+    const iconSize = frustumH * 0.015;
+    icon.scale.set(iconSize * 200, iconSize * 200, 1);
+    icon.renderOrder = 1000;
+    icon.matrixAutoUpdate = true;
+    icon.updateMatrixWorld();
+    viewer.scene.add(icon);
+    allIconSprites.push(icon);
+
+    // CSS2DObject 风速标签(图标上方)
+    const labelDiv = document.createElement('div');
+    labelDiv.textContent = `${+(Math.random() * 3 + 1.5).toFixed(1)} m/s`;
+    labelDiv.style.cssText =
+      'color:#00ffcc;font-size:22px;font-weight:bold;background:rgba(0,0,0,0.7);padding:2px 6px;border-radius:3px;white-space:nowrap;';
+    const cssLabel = new CSS2DObject(labelDiv);
+    cssLabel.position.set(location.x, location.y + 150, 0.1);
+    cssLabel.matrixAutoUpdate = true;
+    cssLabel.updateMatrixWorld();
+    viewer.scene.add(cssLabel);
+    allCssLabels.push(cssLabel);
+
+    markersMap.set(markerId, {
+      deviceId: device.id,
+      worldPos: { x: location.x, y: location.y },
+      mesh,
+      iconSprite: icon,
+      cssLabel,
+    });
     device.markerId = markerId;
     console.log(`[布点] 设备=${device.name} X=${location.x.toFixed(2)} Y=${location.y.toFixed(2)} r=${radius.toFixed(2)}`);
     exitPlacingMode();
@@ -245,8 +297,16 @@
     viewer.scene.remove(m.mesh);
     m.mesh.geometry.dispose();
     (m.mesh.material as THREE.Material).dispose();
+    viewer.scene.remove(m.iconSprite);
+    (m.iconSprite.material as THREE.SpriteMaterial).map?.dispose();
+    m.iconSprite.material.dispose();
+    const ci = allCssLabels.indexOf(m.cssLabel);
+    if (ci > -1) allCssLabels.splice(ci, 1);
+
     const idx = allMeshes.indexOf(m.mesh);
     if (idx > -1) allMeshes.splice(idx, 1);
+    const si = allIconSprites.indexOf(m.iconSprite);
+    if (si > -1) allIconSprites.splice(si, 1);
     markersMap.delete(markerId);
   }
 
@@ -312,13 +372,15 @@
         enableProgressBar: true,
         enableLayoutBar: true,
       });
-
+      await viewer.setFont(fontFiles);
       await viewer.loadModel({ modelId: 'main-plan', name: '总平面布置图', src: dwgSrc }, (event: ProgressEvent) => {
         if (event.total > 0) console.log(`加载: ${Math.round((event.loaded / event.total) * 100)}%`);
       });
 
       viewer.goToHomeView();
       viewerReady.value = true;
+      // initCss();
+
       console.log('[DWG] Viewer2d 就绪');
 
       // === 参照官方示例: ViewerEvent.MouseClick ===
@@ -354,6 +416,10 @@
             if (location) placeMarker(placingDevice.value, location);
           }
         }
+
+        viewer.renderer.render(viewer.scene, viewer.camera);
+        viewer.getCssRender().render(viewer.scene, viewer.camera);
+        css3DRenderer?.render(viewer.scene, viewer.camera);
       });
 
       // === 鼠标移动:实时更新坐标 + 浮动圆点跟随 ===
@@ -374,6 +440,8 @@
             currentCoord.y = wp.y;
             currentCoord.z = wp.z;
           }
+
+          css3DRenderer?.render(viewer.scene, viewer.camera);
         });
       }
 
@@ -399,6 +467,14 @@
         (m.material as THREE.Material).dispose();
       });
       allMeshes.length = 0;
+      allIconSprites.forEach((s) => {
+        viewer!.scene.remove(s);
+        (s.material as THREE.SpriteMaterial).map?.dispose();
+        s.material.dispose();
+      });
+      allIconSprites.length = 0;
+      allCssLabels.forEach((l) => viewer!.scene?.remove(l));
+      allCssLabels.length = 0;
     }
     markersMap.clear();
     if (viewer) {

Some files were not shown because too many files changed in this diff