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>[]) { // 判断是否点击到视频 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;