Explorar el Código

feat: 看板增加3d

yanghao hace 5 días
padre
commit
ece3163c78

+ 1 - 0
package.json

@@ -79,6 +79,7 @@
     "qs": "^6.12.0",
     "sortablejs": "1.15.0",
     "steady-xml": "^0.1.0",
+    "three": "^0.182.0",
     "url": "^0.11.3",
     "v3-jsoneditor": "^0.0.6",
     "video.js": "^7.21.5",

+ 8 - 0
pnpm-lock.yaml

@@ -170,6 +170,9 @@ importers:
       steady-xml:
         specifier: ^0.1.0
         version: 0.1.0
+      three:
+        specifier: ^0.182.0
+        version: 0.182.0
       url:
         specifier: ^0.11.3
         version: 0.11.4
@@ -4872,6 +4875,9 @@ packages:
   text-table@0.2.0:
     resolution: {integrity: sha512-N+8UisAXDGk8PFXP4HAzVR9nbfmVJ3zYLAWiTIoqC5v5isinhr+r5uaO8+7r3BMfuNIufIsA7RdpVgacC2cSpw==}
 
+  three@0.182.0:
+    resolution: {integrity: sha512-GbHabT+Irv+ihI1/f5kIIsZ+Ef9Sl5A1Y7imvS5RQjWgtTPfPnZ43JmlYI7NtCRDK9zir20lQpfg8/9Yd02OvQ==}
+
   through@2.3.8:
     resolution: {integrity: sha512-w89qg7PI8wAdvX60bMDP+bFoD5Dvhm9oLheFp5O4a2QF0cSBGsBX4qZmadPMvVqlLJBBci+WqGGOAPvcDeNSVg==}
 
@@ -10365,6 +10371,8 @@ snapshots:
 
   text-table@0.2.0: {}
 
+  three@0.182.0: {}
+
   through@2.3.8: {}
 
   tiny-svg@3.1.3: {}

+ 0 - 0
src/assets/model/industrial equipment 3d model.glb → src/assets/model/industrialEquipment.glb


+ 116 - 0
src/components/ModelViewer.vue

@@ -0,0 +1,116 @@
+<template>
+  <div ref="container" class="w-full h-full z-999 cursor-pointer"></div>
+</template>
+
+<script setup lang="ts">
+import { ref, onMounted, onUnmounted } from 'vue'
+import * as THREE from 'three'
+import { GLTFLoader } from 'three/examples/jsm/loaders/GLTFLoader.js'
+import { OrbitControls } from 'three/examples/jsm/controls/OrbitControls.js'
+
+const container = ref<HTMLDivElement>()
+
+let scene: THREE.Scene
+let camera: THREE.PerspectiveCamera
+let renderer: THREE.WebGLRenderer
+let controls: OrbitControls
+let model: THREE.Group
+
+const init = () => {
+  scene = new THREE.Scene()
+  // scene.background = new THREE.Color(0x0a0a0a) // 移除深色背景
+
+  camera = new THREE.PerspectiveCamera(75, 1, 0.1, 1000)
+  camera.position.set(3, 3, 3)
+  camera.lookAt(0, 0, 0)
+
+  renderer = new THREE.WebGLRenderer({ antialias: true, alpha: true })
+  renderer.setSize(2000, 1000)
+  renderer.shadowMap.enabled = true
+  renderer.shadowMap.type = THREE.PCFSoftShadowMap
+  container.value?.appendChild(renderer.domElement)
+
+  controls = new OrbitControls(camera, renderer.domElement)
+  controls.enableDamping = true
+  controls.dampingFactor = 0.05
+  controls.enableZoom = true
+  controls.enablePan = false
+
+  const hemisphereLight = new THREE.HemisphereLight(0xffffbb, 0x080820, 2) // 增加强度从1到2
+  scene.add(hemisphereLight)
+
+  const pointLight = new THREE.PointLight(0xffffff, 2, 100) // 增加强度从1到2
+  pointLight.position.set(0, 5, 5)
+  scene.add(pointLight)
+
+  const directionalLight = new THREE.DirectionalLight(0xffffff, 1.5) // 增加强度从0.8到1.5
+  directionalLight.position.set(10, 10, 5)
+  directionalLight.castShadow = true
+  scene.add(directionalLight)
+
+  // 添加额外的环境光
+  const ambientLight = new THREE.AmbientLight(0x404040, 0.6) // 添加环境光
+  scene.add(ambientLight)
+
+  const modelUrl = new URL('../assets/model/industrialEquipment.glb', import.meta.url).href
+  console.log('模型URL:', modelUrl)
+  const loader = new GLTFLoader()
+  loader.load(
+    modelUrl,
+    (gltf) => {
+      console.log('模型加载成功:', gltf)
+      model = gltf.scene
+      model.scale.set(7, 7, 7) // 增加缩放
+      model.position.set(0, 0, 0)
+      scene.add(model)
+    },
+    (progress) => {
+      console.log('模型加载进度:', progress) // 加载进度
+    },
+    (error) => {
+      console.error('模型加载失败:', error)
+    }
+  )
+
+  const animate = () => {
+    requestAnimationFrame(animate)
+    controls.update()
+    if (model) {
+      model.rotation.y += 0.005
+    } else {
+      scene.children.forEach((child) => {
+        if (child instanceof THREE.Mesh && child.geometry instanceof THREE.BoxGeometry) {
+          child.rotation.y += 0.01
+        }
+      })
+    }
+    renderer.render(scene, camera)
+  }
+  animate()
+
+  const resize = () => {
+    if (container.value) {
+      const width = container.value.clientWidth
+      const height = container.value.clientHeight
+      camera.aspect = width / height
+      camera.updateProjectionMatrix()
+      renderer.setSize(width, height)
+    }
+  }
+  window.addEventListener('resize', resize)
+  resize()
+}
+
+onMounted(() => {
+  init()
+})
+
+onUnmounted(() => {
+  if (renderer) {
+    renderer.dispose()
+  }
+  if (controls) {
+    controls.dispose()
+  }
+})
+</script>

+ 6 - 12
src/views/pms/device/completeKanban/index.vue

@@ -109,18 +109,11 @@
         </div>
       </div>
 
-      <!-- Center - 3D View and Compressor Data -->
       <div class="col-span-6 space-y-4">
-        <!-- 3D Factory View -->
         <div class="panel relative overflow-hidden">
-          <div class="relative h-[400px]">
-            <img
-              src="@/assets/imgs/kanban.png"
-              alt="Factory 3D View"
-              class="w-full h-full object-cover"
-            />
-            <div class="absolute inset-0 bg-gradient-to-t from-slate-900/80 to-transparent"></div>
-            <div class="scan-line-fast"></div>
+          <div class="relative h-[450px] flex items-center justify-center">
+            <ModelViewer />
+            <!-- <div class="absolute inset-0 bg-gradient-to-t from-slate-900/80 to-transparent"></div> -->
           </div>
         </div>
 
@@ -192,6 +185,7 @@
 
 <script setup lang="ts">
 import DataRow from './data-row.vue'
+import ModelViewer from '@/components/ModelViewer.vue'
 const leftNavItems = ['箱变', '1050空压机', 'PSA数据', '空气处理镜']
 const rightNavItems = ['主界面', '液驱及中压', '报警监控']
 
@@ -235,14 +229,14 @@ const compressorUnits = [
 </script>
 
 <style scoped>
-@keyframes scan {
+/* @keyframes scan {
   0% {
     top: 0;
   }
   100% {
     top: 100%;
   }
-}
+} */
 
 @keyframes gridMove {
   0% {