import * as THREE from 'three'; import { useAppStore } from '/@/store/modules/app'; import * as dat from 'dat.gui'; const gui = new dat.GUI(); gui.domElement.style = 'position:absolute;top:100px;left:10px;z-index:99999999999999'; // 羊马河 class FireDoorYmh { modelName = 'fireDoorYmh'; model; // group; isLRAnimation = true; // 是否开启左右摇摆动画 direction = 1; // 摇摆方向 animationTimer: NodeJS.Timeout | null = null; // 摇摆开启定时器 player1; player2; deviceDetailCSS3D; playerStartClickTime1 = new Date().getTime(); playerStartClickTime2 = new Date().getTime(); fmClock = new THREE.Clock(); mixers: THREE.AnimationMixer | undefined; appStore = useAppStore(); damperOpenMesh; damperClosedMesh; clipActionArr: Record = { /** 卷帘门动画 */ fengmen: undefined, /** 盖板动画 */ gaiban: undefined, }; constructor(model) { this.model = model; } addLight() { const directionalLight = new THREE.DirectionalLight(0xffffff, 1.5); directionalLight.position.set(344, 690, 344); this.group?.add(directionalLight); directionalLight.target = this.group as THREE.Object3D; const pointLight2 = new THREE.PointLight(0xffeeee, 1, 300); pointLight2.position.set(-4, 10, 1.8); pointLight2.shadow.bias = 0.05; this.group?.add(pointLight2); const pointLight3 = new THREE.PointLight(0xffeeee, 1, 200); pointLight3.position.set(-0.5, -0.5, 0.75); pointLight3.shadow.bias = 0.05; this.group?.add(pointLight3); } resetCamera() { this.model.camera.far = 274; this.model.orbitControls?.update(); this.model.camera.updateProjectionMatrix(); } // 设置模型位置 setModalPosition() { this.group?.scale.set(24, 24, 24); this.group?.position.set(-20, 20, 10); } /* 风门动画 */ render() { if (!this.model) { return; } if (this.mixers && this.fmClock.running) { this.mixers.update(1); } } /* 点击风门 */ mousedownModel(intersects: THREE.Intersection[]) { console.log('摄像头控制信息', intersects); } mouseUpModel() {} /** * 提取风门序列帧,初始化前后门动画 * * 动画序列帧提取操作提示:使用threejs编辑器打开模型并选择模型后点击右下角播放后排查动画元素,找到分界点后手动标记或根据name标记 */ initAnimation() { const group = this.group.children[0]; console.log('debug rr', group.animations[0].tracks); /** 卷帘门的元素名称,pCude34-pCude73 */ if (group) { const tracksA: THREE.KeyframeTrack[] = []; const tracksB: THREE.KeyframeTrack[] = []; group.animations[0].tracks.forEach((track, index) => { if (index < 9) { tracksA.push(track); } else { tracksB.push(track); } }); this.mixers = new THREE.AnimationMixer(group); const fengmen = new THREE.AnimationClip('fengmen', 10, tracksA); const clipA = this.mixers.clipAction(fengmen, group); clipA.clampWhenFinished = true; clipA.loop = THREE.LoopOnce; this.clipActionArr.fengmen = clipA; const gaiban = new THREE.AnimationClip('gaiban', 10, tracksB); const clipB = this.mixers.clipAction(gaiban, group); clipB.clampWhenFinished = true; clipB.loop = THREE.LoopOnce; this.clipActionArr.gaiban = clipB; } } resetAnimate() { if (this.clipActionArr.fengmen) { this.clipActionArr.fengmen.reset(); this.clipActionArr.fengmen.time = 0.1; this.clipActionArr.fengmen.stop(); this.fmClock.stop(); } if (this.clipActionArr.gaiban) { this.clipActionArr.gaiban.reset(); this.clipActionArr.gaiban.time = 0.1; this.clipActionArr.gaiban.stop(); this.fmClock.stop(); } } /** * 播放门开关动画的处理函数 * @param {number} handlerState - 处理状态,1表示开门,2表示关门 * @param {number} [timeScale=0.01] - 动画时间缩放因子,控制动画播放速度 */ play(handlerState, timeScale = 0.01) { console.log('debug ', handlerState); let handler = () => {}; switch (handlerState) { case 1: // 打开门 handler = () => { if (!this.clipActionArr.fengmen) return; this.clipActionArr.fengmen.paused = true; this.clipActionArr.fengmen.reset(); this.clipActionArr.fengmen.time = 0.1; this.clipActionArr.fengmen.timeScale = timeScale; // this.clipActionArr.fengmen.clampWhenFinished = true; this.clipActionArr.fengmen.play(); this.fmClock.start(); // 显示打开前门文字 if (this.damperOpenMesh) this.damperOpenMesh.visible = true; }; break; case 2: // 关闭门 handler = () => { if (!this.clipActionArr.fengmen) return; this.clipActionArr.fengmen.paused = true; this.clipActionArr.fengmen.reset(); // this.clipActionArr.fengmen.time = 9; this.clipActionArr.fengmen.timeScale = -timeScale; // this.clipActionArr.fengmen.clampWhenFinished = true; this.clipActionArr.fengmen.play(); this.fmClock.start(); if (this.damperOpenMesh) this.damperOpenMesh.visible = false; }; break; case 3: // 打开盖板 handler = () => { if (!this.clipActionArr.gaiban) return; this.clipActionArr.gaiban.paused = true; this.clipActionArr.gaiban.reset(); this.clipActionArr.gaiban.time = 0.1; this.clipActionArr.gaiban.timeScale = timeScale; // this.clipActionArr.gaiban.clampWhenFinished = true; this.clipActionArr.gaiban.play(); this.fmClock.start(); if (this.damperOpenMesh) this.damperOpenMesh.visible = false; }; break; case 4: // 关闭盖板 handler = () => { if (!this.clipActionArr.gaiban) return; this.clipActionArr.gaiban.paused = true; this.clipActionArr.gaiban.reset(); // this.clipActionArr.gaiban.time = 9; this.clipActionArr.gaiban.timeScale = -timeScale; // this.clipActionArr.gaiban.clampWhenFinished = true; this.clipActionArr.gaiban.play(); this.fmClock.start(); if (this.damperOpenMesh) this.damperOpenMesh.visible = false; }; break; default: } handler(); } mountedThree() { this.group = new THREE.Object3D(); this.group.name = this.modelName; return new Promise((resolve) => { if (!this.model) { resolve(null); } this.model.setGLTFModel(['fireDoorYmh'], this.group).then(() => { this.setModalPosition(); // 初始化左右摇摆动画; this.initAnimation(); // this.addLight(); // this.model.animate(); // resolve(this.model); // this.damperOpenMesh = this.group.getObjectByName('Damper_Open_2'); // if (this.damperOpenMesh) this.damperOpenMesh.visible = false; // this.damperClosedMesh = this.group.getObjectByName('Damper_Closed_2'); // if (this.damperClosedMesh) this.damperClosedMesh.visible = true; }); }); } destroy() { if (!this.model) return; if (this.mixers && this.clipActionArr.fengmen && this.clipActionArr.gaiban) { this.mixers.uncacheClip(this.clipActionArr.fengmen.getClip()); this.mixers.uncacheAction(this.clipActionArr.fengmen.getClip(), this.group); this.mixers.uncacheClip(this.clipActionArr.gaiban.getClip()); this.mixers.uncacheAction(this.clipActionArr.gaiban.getClip(), this.group); this.mixers.uncacheRoot(this.group); if (this.model.animations[0]) this.model.animations[0].tracks = []; } this.model.clearGroup(this.group); this.clipActionArr.fengmen = undefined; this.clipActionArr.gaiban = undefined; this.mixers = undefined; // document.getElementById('damper3D').parentElement.remove(document.getElementById('damper3D')) } } export default FireDoorYmh;