Koishi 3 mesiacov pred
rodič
commit
abf92be1e8
2 zmenil súbory, kde vykonal 295 pridanie a 66 odobranie
  1. 290 61
      src/components/modelUnpack.vue
  2. 5 5
      src/views/cesium.vue

+ 290 - 61
src/components/modelUnpack.vue

@@ -1,13 +1,34 @@
 
 <template>
-  <div class="modelBox">
-    <div ref="threeCanvas" style="width: 100%; height: 100%"></div>
+  <div
+    class="modelBox"
+    v-loading="modelLoading"
+    element-loading-text="模型加载中...请稍等..."
+    :element-loading-spinner="loadingSvg"
+    element-loading-svg-view-box="-10, -10, 50, 50"
+    element-loading-background="rgba(0, 0, 0, 0.5)"
+  >
+    <div class="l">
+      <div
+        ref="threeCanvas"
+        class="threeCanvas"
+        style="width: 100%; height: 100%"
+      ></div>
+    </div>
+    <div class="r">
+      <div
+        ref="threeToushi"
+        class="threeToushi"
+        style="width: 100%; height: 100%"
+      ></div>
+    </div>
     <div class="bjSelectBox">
       <el-select
         v-model="bj"
         placeholder="完整展示"
         style="width: 300px"
         clearable
+        filterable
         @change="bjChange"
       >
         <el-option
@@ -18,6 +39,15 @@
         />
       </el-select>
     </div>
+    <div class="sliderBarBox">
+      <el-slider v-model="splitWidth" size="small" @change="sliderChange" />
+    </div>
+    <el-tag
+      style="position: absolute; bottom: 5px; left: 5px"
+      closable
+      :type="warning"
+      >这里可以对模型进行解构与透视,蓝色窗体为解构透视窗口,绿色窗体为正投预览窗口,顶部滑块用于切换两个窗口之间的位置,顶部下拉选框用于切换需要解构透视的部件。</el-tag
+    >
   </div>
 </template>
  
@@ -79,23 +109,51 @@ export default {
 
   data() {
     return {
+      splitWidth: 50,
+      modelLoading: false,
+      loadingSvg: `<path class="path" d="
+          M 30 15
+          L 28 17
+          M 25.61 25.61
+          A 15 15, 0, 0, 1, 15 30
+          A 15 15, 0, 1, 1, 27.99 7.5
+          L 15 15
+        " style="stroke-width: 4px; fill: rgba(0, 0, 0, 0)"/>`,
       modelUnpackMap: {
         fengji: "fengji",
-        guangfu: "guangfu",
+        guangfu: "gfSolo",
       },
       ThreeEngine: null,
       scene: null,
       camera: null,
       renderer: null,
+      scene_Toushi: null,
+      camera_Toushi: null,
+      renderer_Toushi: null,
       loader: null,
       baseWidth: 0,
       baseHeight: 0,
       orbitControls: null,
       css3DRenderer: null,
+      orbitControls_Toushi: null,
+      css3DRenderer_Toushi: null,
       animationId: null,
       basicModel: null,
       bj: "",
       bjList: [],
+      modleMap: {
+        fengji: {
+          dizuo13: {
+            name: "底座",
+          },
+          tadiyiceng14: {
+            name: "塔底一层",
+          },
+          zhuzhou15: {
+            name: "主轴",
+          },
+        },
+      },
     };
   },
 
@@ -103,6 +161,7 @@ export default {
     this.initLoader();
     this.initThree({
       dom: this.$refs.threeCanvas,
+      dom_Toushi: this.$refs.threeToushi,
       showGridHelper: true,
     });
   },
@@ -129,6 +188,12 @@ export default {
       }
     },
 
+    sliderChange(value) {
+      const rBox_Toushi = document.querySelector(".r");
+      rBox_Toushi.style.width = `${value}%`;
+      rBox_Toushi.style.left = `${value}%`;
+    },
+
     initThree(options) {
       this.$nextTick(() => {
         const parentDom = getComputedStyle(
@@ -141,7 +206,9 @@ export default {
 
         // 创建3D场景对象Scene
         const scene = new THREE.Scene();
-        scene.background = this.getColor("#add8e6");
+        scene.background = this.getColor("#93bcd3");
+        const scene_Toushi = new THREE.Scene();
+        scene_Toushi.background = this.getColor("#bbd591");
 
         // 相机
         const camera = new PerspectiveCamera(
@@ -155,15 +222,31 @@ export default {
           // 远截面(far)
           options?.cameraOptions?.far || 1000
         );
+        const camera_Toushi = new PerspectiveCamera(
+          // 视野角度(fov)
+          options?.cameraOptions?.fov || 75,
+          // 长宽比(aspect ratio)
+          options?.cameraOptions?.aspectRatio ||
+            this.baseWidth / this.baseHeight,
+          // 近截面(near)
+          options?.cameraOptions?.near || 0.1,
+          // 远截面(far)
+          options?.cameraOptions?.far || 1000
+        );
 
         // 设置摄像机位置和朝向
         camera.position.set(80, 100, 200); // 调整摄像机位置
         camera.lookAt(new THREE.Vector3(0, 0, 0)); // 设置摄像机朝向场景中心
+        camera_Toushi.position.set(80, 100, 200); // 调整摄像机位置
+        camera_Toushi.lookAt(new THREE.Vector3(0, 0, 0)); // 设置摄像机朝向场景中心
 
         // 渲染器
         const renderer = new WebGLRenderer({
           antialias: true, // 开启抗锯齿
         });
+        const renderer_Toushi = new WebGLRenderer({
+          antialias: true, // 开启抗锯齿
+        });
 
         // 添加灯光
         const ambientLight = new THREE.AmbientLight(0xffffff, 5);
@@ -187,13 +270,61 @@ export default {
         directionalLight6.position.set(0, -1, 0);
         scene.add(directionalLight6);
 
+        const ambientLight_Toushi = new THREE.AmbientLight(0xffffff, 5);
+        scene_Toushi.add(ambientLight_Toushi);
+        const directionalLight1_Toushi = new THREE.DirectionalLight(
+          0xffffff,
+          3
+        );
+        directionalLight1_Toushi.position.set(0, 0, 1);
+        scene_Toushi.add(directionalLight1_Toushi);
+        const directionalLight2_Toushi = new THREE.DirectionalLight(
+          0xffffff,
+          3
+        );
+        directionalLight2_Toushi.position.set(0, 0, -1);
+        scene_Toushi.add(directionalLight2_Toushi);
+        const directionalLight3_Toushi = new THREE.DirectionalLight(
+          0xffffff,
+          3
+        );
+        directionalLight3_Toushi.position.set(1, 0, 0);
+        scene_Toushi.add(directionalLight3_Toushi);
+        const directionalLight4_Toushi = new THREE.DirectionalLight(
+          0xffffff,
+          3
+        );
+        directionalLight4_Toushi.position.set(-1, 0, 0);
+        scene_Toushi.add(directionalLight4_Toushi);
+        const directionalLight5_Toushi = new THREE.DirectionalLight(
+          0xffffff,
+          3
+        );
+        directionalLight5_Toushi.position.set(0, 1, 0);
+        scene_Toushi.add(directionalLight5_Toushi);
+        const directionalLight6_Toushi = new THREE.DirectionalLight(
+          0xffffff,
+          3
+        );
+        directionalLight6_Toushi.position.set(0, -1, 0);
+        scene_Toushi.add(directionalLight6_Toushi);
+
         // renderer.setSize(window.innerWidth, window.innerHeight);
         const rendererBox = getComputedStyle(options.dom, null);
         const renderSizeWidth = parseFloat(rendererBox.width);
         const renderSizeHeight = parseFloat(rendererBox.height);
         renderer.setSize(renderSizeWidth, renderSizeHeight);
 
+        const rendererBox_Toushi = getComputedStyle(options.dom_Toushi, null);
+        const renderSizeWidth_Toushi = parseFloat(rendererBox_Toushi.width);
+        const renderSizeHeight_Toushi = parseFloat(rendererBox_Toushi.height);
+        renderer_Toushi.setSize(
+          renderSizeWidth_Toushi,
+          renderSizeHeight_Toushi
+        );
+
         options?.dom?.appendChild(renderer.domElement);
+        options?.dom_Toushi?.appendChild(renderer_Toushi.domElement);
 
         const css3DRenderer = new CSS3DRenderer();
         css3DRenderer.setSize(renderSizeWidth, renderSizeHeight);
@@ -203,6 +334,17 @@ export default {
         css3DRenderer.domElement.style.pointerEvents = "none";
         options.dom.appendChild(css3DRenderer.domElement);
 
+        const css3DRenderer_Toushi = new CSS3DRenderer();
+        css3DRenderer_Toushi.setSize(
+          renderSizeWidth_Toushi,
+          renderSizeHeight_Toushi
+        );
+        css3DRenderer_Toushi.render(scene_Toushi, camera_Toushi);
+        css3DRenderer_Toushi.domElement.style.position = "absolute";
+        css3DRenderer_Toushi.domElement.style.top = 0;
+        css3DRenderer_Toushi.domElement.style.pointerEvents = "none";
+        options.dom_Toushi.appendChild(css3DRenderer_Toushi.domElement);
+
         // 设置鼠标功能键(轨道控制器)
         const orbitControls = new OrbitControls(camera, renderer.domElement);
         // 移动带阻尼
@@ -218,6 +360,57 @@ export default {
           RIGHT: null, // 右键旋转
         };
 
+        orbitControls.addEventListener("end", () => {
+          // 复制位置
+          camera_Toushi.position.copy(camera.position);
+
+          // 复制旋转
+          camera_Toushi.rotation.copy(camera.rotation);
+
+          // 复制up向量
+          camera_Toushi.up.copy(camera.up);
+
+          camera_Toushi.updateMatrixWorld();
+
+          orbitControls_Toushi.target.copy(orbitControls.target);
+          orbitControls.update();
+          orbitControls_Toushi.update();
+        });
+
+        const orbitControls_Toushi = new OrbitControls(
+          camera_Toushi,
+          renderer_Toushi.domElement
+        );
+        // 移动带阻尼
+        orbitControls_Toushi.enableDamping = options.enableDamping || false;
+        // 设置阻尼系数
+        orbitControls_Toushi.dampingFactor = options.dampingFactor || 0;
+        // 自动旋转
+        orbitControls_Toushi.autoRotate = options.autoRotate || false;
+
+        orbitControls_Toushi.mouseButtons = {
+          LEFT: MOUSE.ROTATE, // 左键无功能
+          MIDDLE: MOUSE.PAN, // 中键移动
+          RIGHT: null, // 右键旋转
+        };
+
+        orbitControls_Toushi.addEventListener("end", () => {
+          // 复制位置
+          camera.position.copy(camera_Toushi.position);
+
+          // 复制旋转
+          camera.rotation.copy(camera_Toushi.rotation);
+
+          // 复制up向量
+          camera.up.copy(camera_Toushi.up);
+
+          camera.updateMatrixWorld();
+
+          orbitControls.target.copy(orbitControls_Toushi.target);
+          orbitControls_Toushi.update();
+          orbitControls.update();
+        });
+
         if (options.showGridHelper) {
           // 底图网格 (总长宽,分多少个网格,颜色,轴线颜色,和网格颜色 #e6e8ed)
           const gridHelper = new THREE.GridHelper(
@@ -229,35 +422,73 @@ export default {
           gridHelper.name = "网格地板";
           gridHelper.disalbedDelete = true;
           scene.add(gridHelper);
+
+          const gridHelper_Toushi = new THREE.GridHelper(
+            2000,
+            100,
+            this.getColor("#dedede"),
+            this.getColor("#dedede")
+          );
+          gridHelper_Toushi.name = "网格地板透视";
+          gridHelper_Toushi.disalbedDelete = true;
+          scene_Toushi.add(gridHelper_Toushi);
         }
+
+        const rBox_Toushi = document.querySelector(".r");
+        rBox_Toushi.style.width = `${this.splitWidth}%`;
+        rBox_Toushi.style.left = `${this.splitWidth}%`;
+
+        const canvasStyle_Toushi = document.querySelector(
+          ".threeToushi canvas"
+        );
+        canvasStyle_Toushi.style.position = "absolute";
+        canvasStyle_Toushi.style.left = "-100%";
         // 初始化射线发射器
         let raycaster = new Raycaster();
 
         // 渲染循环
         const animate = () => {
-          this.animationId = requestAnimationFrame(animate);
+          requestAnimationFrame(animate);
           orbitControls.update();
           css3DRenderer.render(scene, camera);
           renderer.render(scene, camera);
         };
 
+        const animate_Toushi = () => {
+          requestAnimationFrame(animate_Toushi);
+          orbitControls_Toushi.update();
+          css3DRenderer_Toushi.render(scene_Toushi, camera_Toushi);
+          renderer_Toushi.render(scene_Toushi, camera_Toushi);
+        };
+
         this.scene = scene;
         this.camera = camera;
         this.renderer = renderer;
         this.orbitControls = orbitControls;
         this.css3DRenderer = css3DRenderer;
 
+        this.scene_Toushi = scene_Toushi;
+        this.camera_Toushi = camera_Toushi;
+        this.renderer_Toushi = renderer_Toushi;
+        this.orbitControls_Toshi = orbitControls_Toushi;
+        this.css3DRenderer_Toushi = css3DRenderer_Toushi;
+
         if (WebGL.isWebGLAvailable()) {
           animate();
+          animate_Toushi();
           // 窗口调整大小时更新渲染器
           window.addEventListener("resize", () => {
             renderer.setSize(window.innerWidth, window.innerHeight);
             camera.aspect = window.innerWidth / window.innerHeight;
             camera.updateProjectionMatrix();
+            renderer_Toushi.setSize(window.innerWidth, window.innerHeight);
+            camera_Toushi.aspect = window.innerWidth / window.innerHeight;
+            camera_Toushi.updateProjectionMatrix();
           });
         } else {
           const warning = WebGL.getWebGLErrorMessage();
           options?.dom?.appendChild(warning);
+          dom_Toushi?.appendChild(warning);
         }
 
         this.addModel({ fileName: this.modelUnpackMap[this.modelUnpackType] });
@@ -282,6 +513,7 @@ export default {
 
     // 添加模型
     addModel({ fileType = "glb", fileName }) {
+      this.modelLoading = true;
       const loader = this.loader[fileType];
       loader.setResourcePath(`./static/model/${fileName}/`);
       loader.load(`./static/model/${fileName}/model.${fileType}`, (result) => {
@@ -290,13 +522,18 @@ export default {
 
         let bjList = [];
         this.basicModel.children.forEach((bj) => {
-          bjList.push(bj);
+          if (bj.name.indexOf("Particle_View") === -1) {
+            bjList.push({ id: bj.id, uuid: bj.uuid, name: bj.name });
+          }
         });
 
         this.bjList = bjList;
+        console.log(1122, bjList);
 
         this.collectMaterialInfo(this.basicModel);
         this.scene.add(this.basicModel);
+        this.scene_Toushi.add(this.basicModel.clone());
+        this.modelLoading = false;
       });
     },
 
@@ -332,6 +569,23 @@ export default {
           center,
           speed
         );
+
+        setTimeout(() => {
+          // 复制位置
+          this.camera_Toushi.position.copy(this.camera.position);
+
+          // 复制旋转
+          this.camera_Toushi.rotation.copy(this.camera.rotation);
+
+          // 复制up向量
+          this.camera_Toushi.up.copy(this.camera.up);
+
+          this.camera_Toushi.updateMatrixWorld();
+
+          this.orbitControls_Toushi.target.copy(this.orbitControls.target);
+          this.orbitControls.update();
+          this.orbitControls_Toushi.update();
+        }, 1000);
       } else {
         // 直接设置新位置
         this.camera.position.copy(cameraPosition);
@@ -341,11 +595,16 @@ export default {
     },
 
     // 平滑移动相机
-    animateCamera(fromPosition, toPosition, fromTarget, toTarget, speed) {
+    animateCamera(fromPosition, toPosition1, fromTarget, toTarget, speed) {
       const that = this;
       const duration = 1000; // 动画持续时间(ms)
       const startTime = Date.now();
 
+      const toPosition = toPosition1;
+      toPosition.x *= 1.03;
+      toPosition.y *= 1.01;
+      toPosition.z *= 1.03;
+
       // 缓动函数
       let easeInOutCubic = (t) => {
         return t < 0.5 ? 4 * t * t * t : 1 - Math.pow(-2 * t + 2, 3) / 2;
@@ -474,60 +733,6 @@ export default {
         }
       });
     },
-
-    // 废弃
-    initThreeJS() {
-      // 获取容器元素
-      const container = this.$refs.threeCanvas;
-
-      // 创建场景
-      const scene = new THREE.Scene();
-      scene.background = this.getColor("#1a1a2e");
-      // scene.background = this.getColor("#add8e6");
-      scene.add(new THREE.AmbientLight(this.getColor("#ffffff"), 2));
-
-      // 创建相机
-      const camera = new THREE.PerspectiveCamera(
-        75,
-        container.clientWidth / container.clientHeight,
-        0.1,
-        1000
-      );
-      camera.position.z = 5;
-
-      // 创建渲染器
-      const renderer = new THREE.WebGLRenderer({ antialias: true });
-      renderer.setSize(container.clientWidth, container.clientHeight);
-      renderer.setPixelRatio(window.devicePixelRatio);
-      container.appendChild(renderer.domElement);
-
-      // 添加灯光
-      const light = new THREE.DirectionalLight(0xffffff, 1);
-      light.position.set(5, 5, 5).normalize();
-      scene.add(light);
-
-      // 添加轨道控制器
-      const controls = new OrbitControls(camera, renderer.domElement);
-      controls.enableDamping = true;
-
-      this.scene = scene;
-      this.camera = camera;
-      this.renderer = renderer;
-      // this.orbitControls = orbitControls;
-      // this.css3DRenderer = css3DRenderer;
-
-      // 窗口调整大小时更新渲染器
-      window.addEventListener("resize", () => {
-        camera.aspect = container.clientWidth / container.clientHeight;
-        camera.updateProjectionMatrix();
-        renderer.setSize(container.clientWidth, container.clientHeight);
-      });
-
-      // this.addModel({
-      //   fileType: "glb",
-      //   fileName: "fjSolo",
-      // });
-    },
   },
 };
 </script>
@@ -537,11 +742,35 @@ export default {
   width: 100%;
   height: 100%;
   position: relative;
+  display: flex;
+  justify-content: flex-start;
+  align-items: center;
+
+  .l,
+  .r {
+    width: 100%;
+    height: 100%;
+    position: absolute;
+    left: 0;
+    top: 0;
+    overflow: hidden;
+  }
+
+  .threeToushi {
+    z-index: 10;
+  }
 
   .bjSelectBox {
     position: absolute;
     left: 5px;
+    top: 25px;
+  }
+
+  .sliderBarBox {
+    position: absolute;
+    left: 5px;
     top: 5px;
+    width: calc(100% - 10px);
   }
 }
 </style>

+ 5 - 5
src/views/cesium.vue

@@ -132,10 +132,10 @@
       style="width: 100%"
       type="border-card"
     >
-      <el-tab-pane label="基础信息" name="jcxx">基础信息</el-tab-pane>
+      <!-- <el-tab-pane label="基础信息" name="jcxx">基础信息</el-tab-pane>
       <el-tab-pane label="视频监控" name="spjk">视频监控</el-tab-pane>
-      <el-tab-pane label="故障查看" name="gzck">故障查看</el-tab-pane>
-      <el-tab-pane label="模型解构" name="mxjg">
+      <el-tab-pane label="故障查看" name="gzck">故障查看</el-tab-pane> -->
+      <el-tab-pane label="模型解构与透视" name="mxjg">
         <ModelUnpack
           :modelUnpackType="modelUnpackType"
           v-if="showFjDialogActiveName === 'mxjg'"
@@ -168,9 +168,9 @@ export default {
 
   data() {
     return {
-      showFjDialog: false,
+      showFjDialog: true,
       modelUnpackType: "fengji",
-      showFjDialogActiveName: "jcxx",
+      showFjDialogActiveName: "mxjg",
       checkMode: false, // 调试模式
       allyShow: false,
       viewer: null,