Browse Source

隧道模型

2545307760@qq.com 7 months ago
parent
commit
44e06d445e

+ 8 - 1
web/src/pinia/modules/screen.js

@@ -6,6 +6,7 @@ export const useScreenStore = defineStore('screen',() => {
     let placeList = []
     let placeList = []
     const tunnelList = reactive([])
     const tunnelList = reactive([])
     const currentTunnel = ref({})
     const currentTunnel = ref({})
+    const screenType = ref('map')
 
 
     const setController = (val) => {
     const setController = (val) => {
         Object.assign(controllerData, val)
         Object.assign(controllerData, val)
@@ -26,6 +27,10 @@ export const useScreenStore = defineStore('screen',() => {
     const setCurrentTunnel = (val) => {
     const setCurrentTunnel = (val) => {
         currentTunnel.value = val
         currentTunnel.value = val
     }
     }
+
+    const setScreenType = (val) => {
+        screenType.value = val
+    }
     return {
     return {
         controllerData,
         controllerData,
         setController,
         setController,
@@ -33,6 +38,8 @@ export const useScreenStore = defineStore('screen',() => {
         setTunnelList,
         setTunnelList,
         placeList,
         placeList,
         currentTunnel,
         currentTunnel,
-        setCurrentTunnel
+        setCurrentTunnel,
+        screenType,
+        setScreenType
     }
     }
 })
 })

+ 0 - 1
web/src/view/admin/dataDashboard/dataDashboard.vue

@@ -164,7 +164,6 @@ const loadModel = () => {
   const loader = new GLTFLoader();
   const loader = new GLTFLoader();
   loader.load('../../public/隧道1.glb', function (gltf){
   loader.load('../../public/隧道1.glb', function (gltf){
       let object = gltf.scene
       let object = gltf.scene
-      console.log(object.children)
       object.children.forEach(item => {
       object.children.forEach(item => {
         if (item.name === '柱体') {
         if (item.name === '柱体') {
           materialOne = item.children[3].material
           materialOne = item.children[3].material

+ 9 - 1
web/src/view/screen/components/map.vue

@@ -26,7 +26,10 @@
         <el-text size="large">{{dialogData.switchType}}</el-text>
         <el-text size="large">{{dialogData.switchType}}</el-text>
       </el-form-item>
       </el-form-item>
       <el-form-item>
       <el-form-item>
-        <el-button type="primary" @click="callParentMethod">查看数据</el-button>
+        <div style="width: 100%; display: flex; justify-content: space-between">
+          <el-button type="primary" @click="callParentMethod">查看数据</el-button>
+<!--          <el-button type="primary" @click="viewModel">查看模型</el-button>-->
+        </div>
       </el-form-item>
       </el-form-item>
     </el-form>
     </el-form>
   </el-dialog>
   </el-dialog>
@@ -84,6 +87,10 @@ export default defineComponent({
       useScreen.setCurrentTunnel(dialogData.value)
       useScreen.setCurrentTunnel(dialogData.value)
       dialogVisible.value = false
       dialogVisible.value = false
     }
     }
+    // const viewModel = () => {
+    //   useScreen.setScreenType('pattern')
+    //   dialogVisible.value = false
+    // }
     return {
     return {
       center,
       center,
       zoom,
       zoom,
@@ -114,6 +121,7 @@ export default defineComponent({
       dialogVisible,
       dialogVisible,
       dialogData,
       dialogData,
       callParentMethod,
       callParentMethod,
+      // viewModel
     };
     };
   },
   },
 });
 });

+ 146 - 93
web/src/view/screen/components/pattern.vue

@@ -1,119 +1,172 @@
 <template>
 <template>
-  <div ref="container" class="model-container"></div>
+  <div ref="container" class="three-container"></div>
 </template>
 </template>
 
 
 <script setup>
 <script setup>
-import { ref, onMounted, onBeforeUnmount } from 'vue'
-import * as THREE from 'three'
-import { OrbitControls } from 'three/examples/jsm/controls/OrbitControls'
-import { GLTFLoader } from 'three/examples/jsm/loaders/GLTFLoader'
-
-const container = ref(null)
-
-// 初始化场景
-const scene = new THREE.Scene()
-// 相机
-const camera = new THREE.PerspectiveCamera(
-    75,
-    window.innerWidth / window.innerHeight,
-    0.1,
-    1000
-)
-// 渲染器
-const renderer = new THREE.WebGLRenderer({
-  antialias: true,
-  alpha: true
-})
-
-// 添加光源
-const ambientLight = new THREE.AmbientLight(0xffffff, 2)
-
-let controls = null
-let model = null
-
-// 初始化场景
-const initScene = () => {
-  if (!container.value) return
-  camera.position.set(30, 30, 30);
-  scene.add(ambientLight)
-
-  // 设置渲染器
-  renderer.setSize(container.value.clientWidth, container.value.clientHeight)
-  renderer.setPixelRatio(window.devicePixelRatio)
-  renderer.outputEncoding = THREE.sRGBEncoding
-  container.value.appendChild(renderer.domElement)
-
-
-  const directionalLight = new THREE.DirectionalLight(0xffffff, 0.8)
-  directionalLight.position.set(5, 5, 5)
-  scene.add(directionalLight)
+import * as THREE from 'three';
+import { GLTFLoader } from 'three/examples/jsm/loaders/GLTFLoader.js';
+import { OrbitControls } from 'three/examples/jsm/controls/OrbitControls.js';
+import { onMounted, onUnmounted, reactive, ref } from 'vue';
+import { useScreenStore } from '@/pinia/modules/screen'
+
+const useScreen = useScreenStore()
+// 获取容器引用
+const container = ref(null);
+
+// 定义 Three.js 相关变量
+let scene, camera, renderer, controls;
+
+// 创建场景
+scene = new THREE.Scene();
+
+// 添加环境光
+const ambientLight = new THREE.AmbientLight(0xffffff, 1);
+
+// 初始化 Three.js 场景
+const initThree = () => {
+  scene.background = null;
+  // textureLoader.load('@/assets/OIP-C.jpg', (texture) => {
+  //   // 将图片设置为场景的背景
+  //   scene.background = texture;
+  // });
+  // 创建相机
+  camera = new THREE.PerspectiveCamera(
+      75,
+      container.value.clientWidth / container.value.clientHeight,
+      0.1,
+      1000
+  );
+  camera.position.set(30, 20, 30);
+
+  // 创建渲染器
+  renderer = new THREE.WebGLRenderer({ antialias: true });
+  renderer.setSize(container.value.clientWidth, container.value.clientHeight);
+  renderer.setClearAlpha(0);
+  // renderer.setClearColor(222842);
+  container.value.appendChild(renderer.domElement);
 
 
   // 添加轨道控制器
   // 添加轨道控制器
   controls = new OrbitControls(camera, renderer.domElement);
   controls = new OrbitControls(camera, renderer.domElement);
   controls.enableDamping = true; // 启用阻尼效果
   controls.enableDamping = true; // 启用阻尼效果
   controls.dampingFactor = 0.05;
   controls.dampingFactor = 0.05;
+
   scene.add(ambientLight);
   scene.add(ambientLight);
 
 
-}
+  // 添加平行光
+  const directionalLight = new THREE.DirectionalLight(0xffffff, 1);
+  directionalLight.position.set(5, 5, 5).normalize();
+  scene.add(directionalLight);
+};
+
+// 存储模型数据
+let materialOne = reactive({})
+let materialTwo = reactive({})
+
+const relayList = reactive([])
+
 
 
-// 加载模型
+// 加载 GLB 模型
 const loadModel = () => {
 const loadModel = () => {
-  const loader = new GLTFLoader()
-
-  loader.load(
-      '../public/隧道1.glb', // 模型路径
-      (gltf) => {
-        model = gltf.scene
-        scene.add(model)
-      },
-      undefined, // 进度回调(可选)
-      (error) => {
-        console.error('Error loading model:', error)
+  const loader = new GLTFLoader();
+  loader.load('../../public/隧道1.glb', function (gltf){
+        let object = gltf.scene
+        object.children.forEach(item => {
+          if (item.name === '柱体') {
+            materialOne = item.children[3].material
+          } else if(item.name === '柱体001') {
+            materialTwo = item.children[3].material
+          }
+        })
+        //gltf.scene获取gltf文件包含的模型数据
+        scene.add(gltf.scene)
+      }, function (xhr) {
+        // 加载进度回调
+        // console.log((xhr.loaded / xhr.total * 100) + '% loaded');
+      }, function (error) {
+        // 加载错误回调
+        // console.error('An error happened', error);
       }
       }
   )
   )
-}
+};
 
 
 // 动画循环
 // 动画循环
 const animate = () => {
 const animate = () => {
-  requestAnimationFrame(animate)
-  if (controls) controls.update()
-  renderer.render(scene, camera)
-}
+  requestAnimationFrame(animate);
+  controls.update(); // 更新控制器
+  renderer.render(scene, camera);
+};
+
+// 亮度调整
+const transparency = ref(0)
+
+const transparencyTwo = ref(0)
+
+// 灯光数据
+const lampData = reactive({})
+
+const judgeLamp = () => {
+  relayList.length = 0
+  if (lampData.switchType === '单灯控制器') {
+    let val1 = lampData.lampValue1
+    let val2 = lampData.lampValue2
+    let judge = {
+      33: [0.8,0],
+      66: [0.5,50],
+      100: [0.2,100],
+    }
+    transparency.value = judge[val1][1]
+    materialOne.opacity = judge[val1][0]
+    transparencyTwo.value = judge[val1][1]
+    materialTwo.opacity = judge[val2][0]
+  } else if(lampData.switchType === '四路控制器') {
+    lampData.devices.forEach(item => {
+      if (item.genre === 6) {
+        relayList.push(item)
+      }
+    })
+    let deviceLamp1 = relayList[0].deviceRelays
+    let deviceLamp2 = relayList[1].deviceRelays
+    let count1 = 0
+    let count2 = 0
+    deviceLamp1.forEach(item => {
+      item.state ? count1++ : count1
+    })
+    deviceLamp2.forEach(item => {
+      item.state ? count2++ : count2
+    })
+    let judgeWay = {
+      1: [0.8,0],
+      2: [0.5,50],
+      3: [0.2,100],
+      4: [0.2,100]
+    }
+    transparency.value = judgeWay[count1][1]
+    materialOne.opacity = judgeWay[count1][0]
+    transparencyTwo.value = judgeWay[count2][1]
+    materialTwo.opacity = judgeWay[count2][0]
+  }
 
 
+}
 
 
+// 组件挂载时初始化
 onMounted(() => {
 onMounted(() => {
-  initScene()
-  loadModel()
-  animate()
-})
-
-onBeforeUnmount(() => {
-  window.removeEventListener('resize', handleResize)
-  if (container.value && container.value.contains(renderer.domElement)) {
-    container.value.removeChild(renderer.domElement)
+  Object.assign(lampData, useScreen.controllerData)
+  initThree();
+  loadModel();
+  animate();
+  setTimeout(function () {
+    judgeLamp()
+  },500)
+});
+
+// 组件卸载时清理资源
+onUnmounted(() => {
+  if (renderer) {
+    renderer.dispose();
   }
   }
-
-  // 清理模型资源
-  if (model) {
-    scene.remove(model)
-    model.traverse((child) => {
-      if (child.isMesh) {
-        child.geometry.dispose()
-        if (Array.isArray(child.material)) {
-          child.material.forEach(m => m.dispose())
-        } else {
-          child.material.dispose()
-        }
-      }
-    })
-  }
-})
+});
 </script>
 </script>
 
 
 <style scoped>
 <style scoped>
-.model-container {
-  width: 100%;
-  height: 100vh;
-  position: relative;
-}
+
 </style>
 </style>

+ 24 - 7
web/src/view/screen/dataScreen.vue

@@ -4,10 +4,10 @@
     <div class="titleImage">
     <div class="titleImage">
       <el-image :src="titleUrl" />
       <el-image :src="titleUrl" />
       <span class="Heading">龙弛智慧隧道系统</span>
       <span class="Heading">龙弛智慧隧道系统</span>
-      <div class="titleOption" style="left: 19%" @click="jumpScreen('map')">
+      <div class="titleOption" style="left: 19%">
         <span>地图</span>
         <span>地图</span>
       </div>
       </div>
-      <div class="titleOption" style="left: 76%" @click="jumpScreen('model')">
+      <div class="titleOption" style="left: 76%">
         <span>模型</span>
         <span>模型</span>
       </div>
       </div>
     </div>
     </div>
@@ -34,7 +34,17 @@
       </el-col>
       </el-col>
       <el-col :span="14" style="display: flex;justify-content: center">
       <el-col :span="14" style="display: flex;justify-content: center">
         <div class="centerBox">
         <div class="centerBox">
-          <Map @call-parent="parentMethod"/>
+          <Map v-if="useScreen.screenType === 'map'"/>
+          <div v-if="useScreen.screenType === 'pattern'" style="position: relative">
+            <el-button
+                style="position: absolute;z-index: 1;"
+                type="info"
+                text
+                @click="returnMap"  icon="ArrowLeft">
+              返回地图
+            </el-button>
+            <Pattern style="position: absolute;z-index: 2;pointer-events: none;"/>
+          </div>
         </div>
         </div>
       </el-col>
       </el-col>
       <el-col :span="5" class="rightBox">
       <el-col :span="5" class="rightBox">
@@ -127,6 +137,7 @@ import singleLamp from "@/assets/icons/singleLamp.png"
 import Chart from "./components/chart.vue";
 import Chart from "./components/chart.vue";
 import warn from '@/assets/main_bottopm_top2.png'
 import warn from '@/assets/main_bottopm_top2.png'
 import Map from './components/map.vue'
 import Map from './components/map.vue'
+import Pattern from './components/pattern.vue'
 import warnTitle from '@/assets/warnTitle.png'
 import warnTitle from '@/assets/warnTitle.png'
 import lightChart from './components/lightChart.vue'
 import lightChart from './components/lightChart.vue'
 import { queryTunnelList } from '@/api/tunnel'
 import { queryTunnelList } from '@/api/tunnel'
@@ -137,6 +148,7 @@ import { updateTunnelLamp } from "@/api/tunnel";
 import { deviceSwitch } from "@/api/device";
 import { deviceSwitch } from "@/api/device";
 import {useScreenStore} from "@/pinia/modules/screen";
 import {useScreenStore} from "@/pinia/modules/screen";
 import {ElMessage} from "element-plus";
 import {ElMessage} from "element-plus";
+
 // 灯光数据
 // 灯光数据
 const lampData = reactive({})
 const lampData = reactive({})
 const useScreen = useScreenStore()
 const useScreen = useScreenStore()
@@ -240,10 +252,6 @@ const changeTransparencyTwo = (e) => {
   }
   }
 }
 }
 
 
-const parentMethod = (e) => {
-  console.log('子组件调用了')
-  console.log(e)
-}
 
 
 const brightness = () => {
 const brightness = () => {
   if (lampData.switchType === '单灯控制器') {
   if (lampData.switchType === '单灯控制器') {
@@ -307,6 +315,11 @@ const yourMethod = (value) => {
   Object.assign(lampData, value)
   Object.assign(lampData, value)
   brightness()
   brightness()
 }
 }
+
+const returnMap = () => {
+  console.log('返回地图')
+  useScreen.setScreenType('map')
+}
 </script>
 </script>
 
 
 <style scoped lang="less">
 <style scoped lang="less">
@@ -546,5 +559,9 @@ const yourMethod = (value) => {
   margin-top: 20px;
   margin-top: 20px;
 }
 }
 
 
+.three-container {
+  height: 800px;
+  width: 100%;
+}
 </style>
 </style>