| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428 | import * as THREE from 'three';import { getTextCanvas, renderVideo } from '/@/utils/threejs/util';import gsap from 'gsap';class lmWindRectSide {  model;  modelName = 'lmcfSide';  group: THREE.Object3D = new THREE.Object3D();  animationTimer;  isLRAnimation = true;  direction = 1;  player1;  player2;  playerStartClickTime1 = new Date().getTime();  playerStartClickTime2 = new Date().getTime();  deviceRunState = '';  tanTouRunState = '';  constructor(model) {    this.model = model;    this.group.name = this.modelName;  }  addLight() {    const directionalLight = new THREE.DirectionalLight(0xffffff, 0.8);    directionalLight.position.set(5.3, 9, 0.8);    this.group.add(directionalLight);    directionalLight.target = this.group;    // gui.add(directionalLight.position, 'x', -10, 20).onChange(function (value) {    //   directionalLight.position.x = Number(value);    //   _this.render();    // });    // gui.add(directionalLight.position, 'y', -50, 50).onChange(function (value) {    //   directionalLight.position.y = Number(value);    //   _this.render();    // });    // gui.add(directionalLight.position, 'z', -20, 20).onChange(function (value) {    //   directionalLight.position.z = Number(value);    //   _this.render();    // });    const spotLight = new THREE.SpotLight();    spotLight.angle = Math.PI / 16;    spotLight.penumbra = 0;    spotLight.castShadow = true;    spotLight.distance = 0;    spotLight.position.set(-470, -500, 500);    this.group.add(spotLight);    spotLight.shadow.camera.near = 0.5; // default    spotLight.shadow.camera.far = 1000; // default    spotLight.shadow.focus = 1;    spotLight.shadow.bias = -0.000002;  }  // 设置模型位置  setModalPosition() {    this.group?.scale.set(22, 22, 22);    this.group?.position.set(-25, 25, 15);  }  addMonitorText(selectData) {    if (!this.group) {      return;    }    const textArr = [      {        text: `煤矿巷道远程测风系统`,        font: 'normal 34px Arial',        color: '#009900',        strokeStyle: '#002200',        x: 125,        y: 42,      },      {        text: `风量(m³/min):`,        font: 'normal 30px Arial',        color: '#009900',        strokeStyle: '#002200',        x: 2,        y: 115,      },      {        text: `${selectData.m3 ? selectData.m3 : '-'}`,        font: 'normal 30px Arial',        color: '#009900',        strokeStyle: '#002200',        x: 331,        y: 115,      },      {        text: `风速(m/s):`,        font: 'normal 30px Arial',        color: '#009900',        strokeStyle: '#002200',        x: 2,        y: 182,      },      {        text: `${selectData.va ? selectData.va : '-'}`,        font: 'normal 30px Arial',        color: '#009900',        strokeStyle: '#002200',        x: 330,        y: 182,      },      {        text: `断面积(MPa): `,        font: 'normal 30px Arial',        color: '#009900',        strokeStyle: '#002200',        x: 2,        y: 245,      },      {        text: `${selectData.fsectarea ? selectData.fsectarea : '-'}`,        font: 'normal 30px Arial',        color: '#009900',        strokeStyle: '#002200',        x: 330,        y: 245,      },      {        text: `煤炭科学技术研究院有限公司研制`,        font: 'normal 28px Arial',        color: '#009900',        strokeStyle: '#002200',        x: 60,        y: 303,      },    ];    getTextCanvas(560, 346, textArr, '').then((canvas: HTMLCanvasElement) => {      const textMap = new THREE.CanvasTexture(canvas); // 关键一步      const textMaterial = new THREE.MeshBasicMaterial({        map: textMap, // 设置纹理贴图        transparent: true,        side: THREE.DoubleSide, // 这里是双面渲染的意思      });      textMaterial.blending = THREE.CustomBlending;      const monitorPlane = this.group?.getObjectByName('monitorText');      if (monitorPlane) {        monitorPlane.material = textMaterial;      } else {        const planeGeometry = new THREE.PlaneGeometry(560, 346); // 平面3维几何体PlaneGeometry        const planeMesh = new THREE.Mesh(planeGeometry, textMaterial);        planeMesh.name = 'monitorText';        planeMesh.scale.set(0.0022, 0.0022, 0.0022);        planeMesh.position.set(3.35, -0.002, -0.41);        this.group?.add(planeMesh);      }    });  }  /* 风门动画 */  render() {    if (!this.model) {      return;    }  }  playCamera(flag) {    const _this = this;    const probeBar = this.group?.getObjectByName('probe_bar') as THREE.Object3D;    const target = new THREE.Vector3();    probeBar.getWorldPosition(target);    const pos = new THREE.Vector3();    pos.set(target.x, target.y, target.z);    const cameraPos = this.model.camera.position;    if (flag == 'start') {      const obj = {        // 相机整体观察位置        x: cameraPos.x,        y: cameraPos.y,        z: cameraPos.z,        // 相机整体预览对应目标观察点        tx: 0,        ty: 0,        tz: 0,      };      gsap.to(obj, {        // 相机局部观察位置        x: pos.x,        y: pos.y,        z: pos.z,        // 相机局部预览对应目标观察点        tx: target.x,        ty: target.y,        tz: target.z,        duration: 0.8,        overwrite: true,        onUpdate: function () {          _this.model.camera.position.set(obj.x, obj.y, obj.z);          _this.model.camera.lookAt(obj.tx, obj.ty, obj.tz);          _this.model.orbitControls.target.set(obj.tx, obj.ty, obj.tz);          // _this.model.orbitControls.update(); //update()函数内会执行camera.lookAt(controls.targe)        },      });    } else if (flag == 'end') {      //    }  }  /* 提取风门序列帧,初始化前后门动画 */  initAnimation() {    const windGroup = new THREE.Group();    windGroup.name = 'lmTanTou';    if (this.group?.children.length) {      for (let i = this.group?.children.length - 1; i > -1; i--) {        const obj = this.group?.children[i];        if (obj.type === 'Mesh' && obj.name && obj.name.startsWith('LMtantou')) {          if (obj.name.startsWith('LMtantou')) {            windGroup.add(obj.clone());            this.group?.remove(obj);          }        }      }    }    this.group?.add(windGroup);  }  /* 点击风窗,风窗全屏 */  mousedownModel(intersects: THREE.Intersection<THREE.Object3D<THREE.Event>>[]) {    // 判断是否点击到视频    intersects.find((intersect) => {      const mesh = intersect.object;      // if (mesh.name === 'player1') {      //   if (new Date().getTime() - this.playerStartClickTime1 < 400) {      //     // 双击,视频放大      //     if (this.player1) {      //       this.player1.requestFullscreen();      //     }      //   }      //   this.playerStartClickTime1 = new Date().getTime();      //   return true;      // }      return false;    });    // console.log('999999999', this.model.camera.position, this.model.orbitControls);  }  mouseUpModel() {}  resetModel() {    clearTimeout(this.animationTimer);  }  // 播放动画  play(flag, isDirect = false) {    const probeBar = this.group?.getObjectByName('probe_bar') as THREE.Object3D;    const cfTanTou = probeBar.getObjectByName('probe_') as THREE.Object3D;    if (!probeBar || !cfTanTou) return;    switch (flag) {      case 'up':        if (!isDirect) {          if (this.deviceRunState == 'down') probeBar.position.setY(-0.3);          gsap.to(probeBar['position'], {            y: 0.35,            duration: Math.abs(probeBar['position']['y'] - 0.35) * 25,            overwrite: true,          });        } else {          gsap.to(probeBar['position'], {            y: 0.35,            duration: 0,            overwrite: true,          });        }        break;      case 'center':        if (!isDirect) {          gsap.to(probeBar['position'], {            y: 0.05,            duration: Math.abs(probeBar['position']['y'] - 0.05) * 50,            overwrite: true,          });        } else {          gsap.to(probeBar['position'], {            y: 0.05,            duration: 0,            overwrite: true,          });        }        break;      case 'down':        if (!isDirect) {          gsap.to(probeBar['position'], {            y: -0.3,            duration: Math.abs(probeBar['position']['y'] + 0.3) * 50,            overwrite: true,          });        } else {          gsap.to(probeBar['position'], {            y: -0.3,            duration: 0,            overwrite: true,          });        }        break;      case 'left':        if (!isDirect) {          gsap.to(cfTanTou['position'], {            z: 325.262,            duration: Math.abs(cfTanTou['position']['z'] - 325.262) * 0.05,            overwrite: true,          });        } else {          gsap.to(cfTanTou['position'], {            z: 325.262,            duration: 0,            overwrite: true,          });        }        break;      case 'middle':        if (!isDirect) {          gsap.to(cfTanTou['position'], {            z: -6.436,            duration: Math.abs(cfTanTou['position']['z'] + 6.436) * 0.05,            overwrite: true,          });        } else {          gsap.to(cfTanTou['position'], {            z: -6.436,            duration: 0,            overwrite: true,          });        }        break;      case 'right':        if (!isDirect) {          gsap.to(cfTanTou['position'], {            z: -338.22,            duration: Math.abs(cfTanTou['position']['z'] + 338.22) * 0.05,            overwrite: true,          });        } else {          gsap.to(cfTanTou['position'], {            z: -338.22,            duration: 0,            overwrite: true,          });        }        break;    }  }  async initCamera(dom1?) {    const videoPlayer1 = dom1;    let monitorPlane: THREE.Mesh | null = null;    const canvas = await getTextCanvas(320, 180, '', 'noSinge.png');    const textMap = new THREE.CanvasTexture(canvas); // 关键一步    const textMaterial = new THREE.MeshBasicMaterial({      map: textMap, // 设置纹理贴图      transparent: true,      side: THREE.DoubleSide, // 这里是双面渲染的意思    });    textMaterial.blending = THREE.CustomBlending;    monitorPlane = this.group?.getObjectByName('noPlayer');    if (monitorPlane) {      monitorPlane.material = textMaterial;    } else {      const planeGeometry = new THREE.PlaneGeometry(100, 100); // 平面3维几何体PlaneGeometry      monitorPlane = new THREE.Mesh(planeGeometry, textMaterial);      textMaterial.dispose();      planeGeometry.dispose();    }    const videoPlayer = this.group.getObjectByName('player1');    if (videoPlayer) {      this.model.clearMesh(videoPlayer);      this.group.remove(videoPlayer);    }    const noPlayer1 = this.group.getObjectByName('noPlayer1');    if (noPlayer1) {      this.model.clearMesh(noPlayer1);      this.group.remove(noPlayer1);    }    if (!videoPlayer1 && videoPlayer1 === null) {      monitorPlane.name = 'noPlayer1';      monitorPlane.scale.set(0.013, 0.007, 0.012);      monitorPlane.position.set(-2.67, 0.0, -0.39);      this.group?.add(monitorPlane);    } else if (videoPlayer1) {      const mesh = renderVideo(this.group, videoPlayer1, 'player1');      if (mesh) {        mesh?.scale.set(0.042, 0.036, 0.022);        mesh?.position.set(-2.65, 0.03, -0.39);        mesh.rotation.y = -Math.PI;        this.group.add(mesh);      }    }  }  mountedThree() {    return new Promise((resolve) => {      this.model.setGLTFModel([this.modelName]).then((gltf) => {        if (gltf[0]) {          this.group = gltf[0];          this.setModalPosition();          const probeBar = this.group?.getObjectByName('probe_bar') as THREE.Object3D;          probeBar.position.setY(0.35);          this.addLight();        }        resolve(null);      });    });  }  destroy() {    if (this.group) {      this.model.clearGroup(this.group);    }    this.model = null;    this.group = null;  }}export default lmWindRectSide;
 |