import * as THREE from 'three'; import { setModalCenter, getTextCanvas, renderVideo } from '/@/utils/threejs/util'; import Smoke from '/@/views/vent/comment/threejs/Smoke'; import gsap from 'gsap'; // import * as dat from 'dat.gui'; // const gui = new dat.GUI(); // gui.domElement.style = 'position:absolute;top:100px;left:10px;z-index:99999999999999'; class balancePressBase { model; modelName = 'balancePress'; group: THREE.Object3D | null = null; topSmoke: Smoke | null = null; downSmoke: Smoke | null = null; outSmoke: Smoke | null = null; constructor(model) { this.model = model; } addLight() { const directionalLight = new THREE.DirectionalLight(0xffffff, 1); directionalLight.position.set(34, 7, -61); this.group?.add(directionalLight); directionalLight.target = this.group as THREE.Object3D; // gui.add(directionalLight.position, 'x', -200, 200); // gui.add(directionalLight.position, 'y', -200, 200); // gui.add(directionalLight.position, 'z', -200, 200); const pointLight5 = new THREE.PointLight(0xffffff, 0.8, 120); pointLight5.position.set(75, -44, 75); pointLight5.shadow.bias = 0.05; this.group?.add(pointLight5); const pointLight7 = new THREE.PointLight(0xffffff, 1, 1000); pointLight7.position.set(-7, 100, 8.5); pointLight7.shadow.bias = 0.05; this.group?.add(pointLight7); // gui.add(directionalLight.position, 'x', -100, 100); // gui.add(directionalLight.position, 'y', -100, 100); // gui.add(directionalLight.position, 'z', -100, 100); // gui.add(pointLight5.position, 'x', -500, 500); // gui.add(pointLight5.position, 'y', -500, 500); // gui.add(pointLight5.position, 'z', -500, 500); } /* 添加监控数据 */ addText(selectData) { if (!this.group) { return; } const textArr = [ { text: `煤矿巷道远程局部风机系统`, font: 'normal 30px Arial', color: '#009900', strokeStyle: '#002200', x: 50, y: 105, }, { text: `进风量(m³/min):`, font: 'normal 30px Arial', color: '#009900', strokeStyle: '#002200', x: 0, y: 160, }, { text: `${selectData.frontRearDP}`, font: 'normal 30px Arial', color: '#009900', strokeStyle: '#002200', x: 290, y: 160, }, { text: `供风量(m³/min): `, font: 'normal 30px Arial', color: '#009900', strokeStyle: '#002200', x: 0, y: 217, }, { text: ` ${selectData.sourcePressure}`, font: 'normal 30px Arial', color: '#009900', strokeStyle: '#002200', x: 280, y: 217, }, { text: `故障诊断:`, font: 'normal 30px Arial', color: '#009900', strokeStyle: '#002200', x: 0, y: 275, }, { text: `${selectData.warnLevel_str ? selectData.warnLevel_str : '-'}`, font: 'normal 30px Arial', color: '#009900', strokeStyle: '#002200', x: 280, y: 275, }, { text: `煤炭科学技术研究院有限公司研制`, font: 'normal 28px Arial', color: '#009900', strokeStyle: '#002200', x: 20, y: 325, }, ]; getTextCanvas(526, 346, textArr, '').then((canvas: HTMLCanvasElement) => { const textMap = new THREE.CanvasTexture(canvas); // 关键一步 const textMaterial = new THREE.MeshBasicMaterial({ // 关于材质并未讲解 实操即可熟悉 这里是漫反射类似纸张的材质,对应的就有高光类似金属的材质. map: textMap, // 设置纹理贴图 transparent: true, side: THREE.FrontSide, // 这里是双面渲染的意思 }); textMaterial.blending = THREE.CustomBlending; const monitorPlane = this.group?.getObjectByName('monitorText') as THREE.Mesh; if (monitorPlane) { monitorPlane.material = textMaterial; } else { const planeGeometry = new THREE.PlaneGeometry(526, 346); // 平面3维几何体PlaneGeometry const planeMesh = new THREE.Mesh(planeGeometry, textMaterial); planeMesh.name = 'monitorText'; planeMesh.scale.set(0.0135, 0.0135, 0.0135); planeMesh.position.set(57.66, 0.81, 18.19); this.group?.add(planeMesh); } }); } addVideo() { const videoPlayer1 = document.getElementById('jb-player1')?.getElementsByClassName('vjs-tech')[0]; if (videoPlayer1) { const mesh = renderVideo(this.group, videoPlayer1, 'player1'); if (mesh) { mesh.scale.set(0.222, 0.19, 0.2); mesh.position.set(-84.87, 0.298, 24.76); mesh.rotation.y = -Math.PI / 2; this.group?.add(mesh); } } else { const textArr = [ { text: `无信号输入`, font: 'normal 40px Arial', color: '#009900', strokeStyle: '#002200', x: 170, y: 40, }, ]; 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('noPlayer'); if (monitorPlane) { monitorPlane.material = textMaterial; } else { const planeGeometry = new THREE.PlaneGeometry(100, 100); // 平面3维几何体PlaneGeometry const planeMesh = new THREE.Mesh(planeGeometry, textMaterial); if (!videoPlayer1) { planeMesh.name = 'noPlayer'; planeMesh.scale.set(0.1, 0.075, 0); planeMesh.position.set(65.78, -2.68, 18.06); this.group?.add(planeMesh.clone()); } } }); } } playSmoke = (controlType, deviceType, frequency, state, duration?) => { if (frequency) { this.setSmokeFrequency(deviceType, frequency); } if (controlType === 'startSmoke') { this.runFly(deviceType, state, duration); } }; async initFly() { // const fanObj = this.group?.getObjectByName('Equalization'); const mesh = new THREE.Mesh(); mesh.matrix = new THREE.Matrix4(); mesh.position.set(35.251, 0.852, -35.243); mesh.scale.set(0.001, 0.001, 0.001); mesh.updateMatrix(); if (!this.group) return; const topCurve = [ { path0: new THREE.Vector3(14485.279, 1370.746, 56053.556).applyMatrix4(mesh.matrix), path1: new THREE.Vector3(7555.8, 1370.746, 54190.156).applyMatrix4(mesh.matrix), isSpread: true, spreadDirection: -1, // }, ]; const downCurve = [ { path0: new THREE.Vector3(14485.279, -1370.746, 56053.556).applyMatrix4(mesh.matrix), path1: new THREE.Vector3(7555.82, -1370.746, 54190.156).applyMatrix4(mesh.matrix), isSpread: true, spreadDirection: -1, // }, ]; const outCurve = [ { path0: new THREE.Vector3(-7555.818, -23.02, 11190.152).applyMatrix4(mesh.matrix), path1: new THREE.Vector3(-7555.818, -23.02, 165.96).applyMatrix4(mesh.matrix), isSpread: true, spreadDirection: 1, // 1是由小变大,-1是由大变小 }, ]; if (!this.topSmoke) { this.topSmoke = new Smoke('/model/img/texture-smoke.png', '#ffffff', 0, 0.8, 0.05, 20); this.topSmoke.setPath(topCurve); await this.topSmoke.setPoints(); this.group.add(this.topSmoke.points); } if (!this.downSmoke) { this.downSmoke = new Smoke('/model/img/texture-smoke.png', '#ffffff', 0, 0.8, 0.05, 20); this.downSmoke.setPath(downCurve); await this.downSmoke.setPoints(); this.group.add(this.downSmoke.points); } if (!this.outSmoke) { this.outSmoke = new Smoke('/model/img/texture-smoke.png', '#ffffff', 0, 0.8, 0.05, 20); this.outSmoke.setPath(outCurve); await this.outSmoke.setPoints(); this.group.add(this.outSmoke.points); } } runFly(deviceType, state, duration?) { if (state === 'open') { if (deviceType === 'top') { if (this.downSmoke?.frameId) { this.downSmoke.stopSmoke(); } this.topSmoke?.startSmoke(duration); } else { if (this.topSmoke?.frameId) { this.topSmoke.stopSmoke(); } this.downSmoke?.startSmoke(duration); } this.outSmoke?.startSmoke(duration); } else { if (this.downSmoke?.frameId) { this.downSmoke?.stopSmoke(); } if (this.topSmoke?.frameId) { this.topSmoke?.stopSmoke(); } if (this.outSmoke?.frameId) { this.outSmoke?.stopSmoke(); } } } setSmokeFrequency = (deviceType, frequency) => { if (!this.topSmoke) return; const life = (frequency - 30) * 25; const duration = (Math.abs(life - this.topSmoke.life) / 500) * 25; let smoke; if (deviceType === 'top') { smoke = this.topSmoke; } else { smoke = this.downSmoke; } gsap.to(smoke, { life: life, duration: duration, ease: 'easeInCubic', overwrite: true, }); }; clearFly = () => { if (this.topSmoke) this.topSmoke.clearSmoke(); if (this.downSmoke) this.downSmoke.clearSmoke(); if (this.outSmoke) this.outSmoke.clearSmoke(); }; mountedThree() { return new Promise((resolve) => { this.model.setGLTFModel([this.modelName]).then(async (gltf) => { this.group = gltf[0]; if (this.group) { this.group?.scale.set(0.1, 0.1, 0.1); await this.initFly(); setModalCenter(this.group); resolve(null); this.addLight(); } }); }); } destroy() { this.clearFly(); this.model.clearGroup(this.group); this.model = null; this.group = null; } } export default balancePressBase;