|
@@ -0,0 +1,787 @@
|
|
|
+import * as THREE from 'three';
|
|
|
+import { CSS3DObject } from 'three/examples/jsm/renderers/CSS3DRenderer.js';
|
|
|
+import Smoke from '/@/views/vent/comment/threejs/Smoke';
|
|
|
+import { PathPointList, PathGeometry } from 'three.path';
|
|
|
+import gsap from 'gsap';
|
|
|
+
|
|
|
+class mainWindLj3 {
|
|
|
+ model;
|
|
|
+ modelName = 'main';
|
|
|
+ group: THREE.Group | null = null; // 主通风机场景
|
|
|
+ motorGroup1: THREE.Group | null = null; //电机
|
|
|
+ motorGroup2: THREE.Group | null = null; //电机
|
|
|
+ motorGroup3: THREE.Group | null = null; //电机
|
|
|
+ airJin1: THREE.Mesh | null = null; //风向箭头
|
|
|
+ airJin2: THREE.Mesh | null = null; //风向箭头
|
|
|
+ airChu1: THREE.Mesh | null = null; //风向箭头
|
|
|
+ airChu2: THREE.Mesh | null = null; //风向箭头
|
|
|
+ gearFront = {
|
|
|
+ gear1: null, //扇叶
|
|
|
+ gear2: null, //扇叶
|
|
|
+ gear1Direction: -1,
|
|
|
+ gear2Direction: 1,
|
|
|
+ gearFrameId: undefined,
|
|
|
+ gearRotateFactor: 0.5,
|
|
|
+ endGearRotateFactor: 3,
|
|
|
+ };
|
|
|
+ gearCenter = {
|
|
|
+ gear1: null, //扇叶
|
|
|
+ gear2: null, //扇叶
|
|
|
+ gear1Direction: -1, // 扇叶转动方向
|
|
|
+ gear2Direction: 1, // 扇叶转动方向
|
|
|
+ gearFrameId: undefined,
|
|
|
+ gearRotateFactor: 0.5, // 扇叶转动因素
|
|
|
+ endGearRotateFactor: 3, // 扇叶最终转动速度因素
|
|
|
+ };
|
|
|
+ gearBack = {
|
|
|
+ gear1: null, //扇叶
|
|
|
+ gear2: null, //扇叶
|
|
|
+ gear1Direction: -1, // 扇叶转动方向
|
|
|
+ gear2Direction: 1, // 扇叶转动方向
|
|
|
+ gearFrameId: undefined,
|
|
|
+ gearRotateFactor: 0.5, // 扇叶转动因素
|
|
|
+ endGearRotateFactor: 3, // 扇叶最终转动速度因素
|
|
|
+ };
|
|
|
+ oldMaterial: THREE.Material = new THREE.MeshStandardMaterial();
|
|
|
+ // smoke;
|
|
|
+ frontSmoke: Smoke | null = null; // 前面风流对象
|
|
|
+ centerSmoke: Smoke | null = null; // 前面风流对象
|
|
|
+ backSmoke: Smoke | null = null; // 后面风流对象
|
|
|
+ player1; // 视频播放器
|
|
|
+ playerStartClickTime1 = new Date().getTime();
|
|
|
+ frontWindowGroup;
|
|
|
+ backWindowGroup;
|
|
|
+ windowAngle = 0;
|
|
|
+ clock = new THREE.Clock();
|
|
|
+ material;
|
|
|
+ airTexture;
|
|
|
+ offset = 0;
|
|
|
+ direction = 0; // -1 代表反向,1代表正向
|
|
|
+ arrowMesh;
|
|
|
+ constructor(model, playerVal1) {
|
|
|
+ this.model = model;
|
|
|
+ this.player1 = playerVal1;
|
|
|
+ }
|
|
|
+ // 添加 cssObject
|
|
|
+ addCssText() {
|
|
|
+ if (!this.group) {
|
|
|
+ return;
|
|
|
+ }
|
|
|
+
|
|
|
+ const mainWindLj3 = this.group?.getObjectByName('mainWindLj3');
|
|
|
+ const fengji = mainWindLj3?.getObjectByName('FengJi_SanFengTong');
|
|
|
+ const fengji1 = fengji?.getObjectByName('Feng1_1');
|
|
|
+ const fengji2 = fengji?.getObjectByName('Feng2_1');
|
|
|
+ const fengji3 = fengji?.getObjectByName('Feng3_2');
|
|
|
+
|
|
|
+ // #1
|
|
|
+ if (!this.group.getObjectByName('monitorText1')) {
|
|
|
+ const worldPosition = new THREE.Vector3();
|
|
|
+ fengji1?.getObjectByName('Feng1_7')?.getWorldPosition(worldPosition);
|
|
|
+ const element = document.getElementById('inputBox') as HTMLElement;
|
|
|
+ if (element) {
|
|
|
+ const mainCSS3D = new CSS3DObject(element);
|
|
|
+ mainCSS3D.name = 'monitorText1';
|
|
|
+ mainCSS3D.scale.set(0.09, 0.09, 0.09);
|
|
|
+ mainCSS3D.position.set(worldPosition.x + 12, worldPosition.y - 20, worldPosition.z - 20);
|
|
|
+ mainCSS3D.lookAt(worldPosition.x + 12, worldPosition.y - 0, worldPosition.z + 2);
|
|
|
+ this.group.add(mainCSS3D);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ debugger;
|
|
|
+ //#2
|
|
|
+ if (!this.group.getObjectByName('monitorText2')) {
|
|
|
+ const worldPosition = new THREE.Vector3();
|
|
|
+ fengji2?.getObjectByName('Feng2_44')?.getWorldPosition(worldPosition);
|
|
|
+ const element = document.getElementById('inputBox1') as HTMLElement;
|
|
|
+ if (element) {
|
|
|
+ const mainCSS3D = new CSS3DObject(element);
|
|
|
+ mainCSS3D.name = 'monitorText2';
|
|
|
+ mainCSS3D.scale.set(0.09, 0.09, 0.09);
|
|
|
+ mainCSS3D.position.set(worldPosition.x + 12, worldPosition.y - 20, worldPosition.z - 20);
|
|
|
+ mainCSS3D.lookAt(worldPosition.x + 12, worldPosition.y - 0, worldPosition.z + 2);
|
|
|
+ this.group.add(mainCSS3D);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ // #3
|
|
|
+ if (!this.group.getObjectByName('monitorText3')) {
|
|
|
+ const worldPosition = new THREE.Vector3();
|
|
|
+ fengji3?.getObjectByName('Feng3_43')?.getWorldPosition(worldPosition);
|
|
|
+ const element = document.getElementById('inputBox2') as HTMLElement;
|
|
|
+ if (element) {
|
|
|
+ const mainCSS3D = new CSS3DObject(element);
|
|
|
+ mainCSS3D.name = 'monitorText3';
|
|
|
+ mainCSS3D.scale.set(0.09, 0.09, 0.09);
|
|
|
+ mainCSS3D.position.set(worldPosition.x + 12, worldPosition.y - 20, worldPosition.z - 20);
|
|
|
+ mainCSS3D.lookAt(worldPosition.x + 12, worldPosition.y - 0, worldPosition.z + 2);
|
|
|
+ this.group.add(mainCSS3D);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ clearCssText() {
|
|
|
+ if (this.group) {
|
|
|
+ const mainCSS3D1 = this.group.getObjectByName('monitorText1');
|
|
|
+ const mainCSS3D2 = this.group.getObjectByName('monitorText2');
|
|
|
+ const mainCSS3D3 = this.group.getObjectByName('monitorText3');
|
|
|
+ if (mainCSS3D1) this.group.remove(mainCSS3D1);
|
|
|
+ if (mainCSS3D2) this.group.remove(mainCSS3D2);
|
|
|
+ if (mainCSS3D3) this.group.remove(mainCSS3D3);
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ addEcharts() {
|
|
|
+ const echartsBox = document.getElementById('fan-echarts');
|
|
|
+ if (echartsBox) {
|
|
|
+ const canvasObj = echartsBox.getElementsByTagName('canvas')[0];
|
|
|
+ // 将canvas 纹理转换为材质
|
|
|
+ const echartsMap = new THREE.CanvasTexture(canvasObj); // 关键一步
|
|
|
+ const echartsMaterial = new THREE.MeshBasicMaterial({
|
|
|
+ map: echartsMap, // 设置纹理贴图
|
|
|
+ transparent: true,
|
|
|
+ side: THREE.FrontSide, // 这里是双面渲染的意思
|
|
|
+ });
|
|
|
+ echartsMaterial.blending = THREE.CustomBlending;
|
|
|
+ const monitorPlane = this.group?.getObjectByName('monitorEcharts');
|
|
|
+ if (monitorPlane) {
|
|
|
+ monitorPlane.material = echartsMaterial;
|
|
|
+ } else {
|
|
|
+ const planeGeometry = new THREE.PlaneGeometry(17.6, 9.9); // 平面3维几何体PlaneGeometry
|
|
|
+ const planeMesh = new THREE.Mesh(planeGeometry, echartsMaterial);
|
|
|
+ planeMesh.name = 'monitorEcharts';
|
|
|
+ planeMesh.scale.set(1, 1, 1);
|
|
|
+ planeMesh.position.set(-47.38, 13.227, -21.79);
|
|
|
+ this.group?.add(planeMesh);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ /* 更新动画 */
|
|
|
+ render() {
|
|
|
+ if (!this.model) {
|
|
|
+ return;
|
|
|
+ }
|
|
|
+ if (this.airTexture) {
|
|
|
+ this.airTexture.offset.x = this.offset;
|
|
|
+ this.offset -= this.clock.getDelta() * 2;
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ /* 点击风窗,风窗全屏 */
|
|
|
+ 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;
|
|
|
+ });
|
|
|
+ }
|
|
|
+
|
|
|
+ mouseUpModel() {}
|
|
|
+
|
|
|
+ async setDeviceFrequency(deviceType, state, frequencyVal?) {
|
|
|
+ // 调节频率
|
|
|
+ if (frequencyVal) {
|
|
|
+ this.resetSmokeParam(deviceType, frequencyVal, 0);
|
|
|
+ }
|
|
|
+ this.openOrCloseValve(deviceType, state, 0);
|
|
|
+ this.startGearAnimation(deviceType, state, '', 0);
|
|
|
+ if (deviceType === 'front') {
|
|
|
+ this.frontSmoke?.startSmoke();
|
|
|
+ } else if (deviceType === 'center') {
|
|
|
+ this.centerSmoke?.startSmoke();
|
|
|
+ } else {
|
|
|
+ this.backSmoke?.startSmoke();
|
|
|
+ }
|
|
|
+ setTimeout(() => {
|
|
|
+ this.lookMotor(deviceType, state, 10);
|
|
|
+ }, 2000);
|
|
|
+ }
|
|
|
+
|
|
|
+ async openDevice(deviceType, smokeDirection, frequencyVal, duration?) {
|
|
|
+ if (smokeDirection) {
|
|
|
+ this.setSmokeDirection(deviceType, smokeDirection);
|
|
|
+ }
|
|
|
+ let smoke;
|
|
|
+ if (deviceType === 'front') {
|
|
|
+ smoke = this.frontSmoke;
|
|
|
+ } else if (deviceType === 'center') {
|
|
|
+ smoke = this.centerSmoke;
|
|
|
+ } else {
|
|
|
+ smoke = this.backSmoke;
|
|
|
+ }
|
|
|
+ if (!smoke.frameId) {
|
|
|
+ await this.lookMotor(deviceType, 'open', duration);
|
|
|
+ await this.openOrCloseValve(deviceType, 'open', duration);
|
|
|
+ this.startGearAnimation(deviceType, 'open', smokeDirection, frequencyVal, duration);
|
|
|
+ smoke.startSmoke(duration);
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ async closeDevice(deviceType, flag = true) {
|
|
|
+ let smoke;
|
|
|
+ if (deviceType === 'front') {
|
|
|
+ smoke = this.frontSmoke;
|
|
|
+ } else if (deviceType === 'back') {
|
|
|
+ smoke = this.backSmoke;
|
|
|
+ } else {
|
|
|
+ smoke = this.centerSmoke;
|
|
|
+ }
|
|
|
+ if (smoke && smoke.frameId) {
|
|
|
+ if (flag) {
|
|
|
+ smoke.stopSmoke();
|
|
|
+ await this.openOrCloseValve(deviceType, 'close');
|
|
|
+ this.startGearAnimation(deviceType, 'close', '', null);
|
|
|
+ await this.lookMotor(deviceType, 'close');
|
|
|
+ } else {
|
|
|
+ smoke.stopSmoke(0);
|
|
|
+ await this.openOrCloseValve(deviceType, 'close', 0);
|
|
|
+ this.startGearAnimation(deviceType, 'close', '', null, 0);
|
|
|
+ await this.lookMotor(deviceType, 'close', 0);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ async setSmokeDirection(deviceType, smokeDirection) {
|
|
|
+ let smoke;
|
|
|
+ const pathPoints: THREE.Vector3[] = [];
|
|
|
+ const windowPositivePath = [
|
|
|
+ {
|
|
|
+ path0: new THREE.Vector3(4.441, 20.267, 3.614),
|
|
|
+ path1: new THREE.Vector3(5.041, 6.806, 3.614),
|
|
|
+ isSpread: true,
|
|
|
+ spreadDirection: -1, //
|
|
|
+ },
|
|
|
+ {
|
|
|
+ path0: new THREE.Vector3(7.441, 0.806, 3.614),
|
|
|
+ path1: new THREE.Vector3(41.583, 1.485, 3.614),
|
|
|
+ isSpread: false,
|
|
|
+ spreadDirection: 0, //
|
|
|
+ },
|
|
|
+ {
|
|
|
+ path0: new THREE.Vector3(41.583, 1.485, 3.614),
|
|
|
+ path1: new THREE.Vector3(42.741, 5.364, 3.614),
|
|
|
+ isSpread: false,
|
|
|
+ spreadDirection: 0,
|
|
|
+ },
|
|
|
+ {
|
|
|
+ path0: new THREE.Vector3(42.741, 5.364, 3.614),
|
|
|
+ path1: new THREE.Vector3(44.741, 17.267, 3.614),
|
|
|
+ isSpread: true,
|
|
|
+ spreadDirection: 1, // 1是由小变大(出),-1是由大变小(进)
|
|
|
+ },
|
|
|
+ ];
|
|
|
+ const windowInversePath = [
|
|
|
+ {
|
|
|
+ path0: new THREE.Vector3(44.741, 17.267, 3.614),
|
|
|
+ path1: new THREE.Vector3(42.741, 5.364, 3.614),
|
|
|
+ isSpread: true,
|
|
|
+ spreadDirection: -1, //
|
|
|
+ },
|
|
|
+ {
|
|
|
+ path0: new THREE.Vector3(42.741, 5.364, 3.614),
|
|
|
+ path1: new THREE.Vector3(41.583, 1.485, 3.614),
|
|
|
+ isSpread: false,
|
|
|
+ spreadDirection: 0, //
|
|
|
+ },
|
|
|
+ {
|
|
|
+ path0: new THREE.Vector3(41.583, 1.485, 3.614),
|
|
|
+ path1: new THREE.Vector3(7.441, 0.806, 3.614),
|
|
|
+ isSpread: false,
|
|
|
+ spreadDirection: 0, // 1是由小变大,-1是由大变小
|
|
|
+ },
|
|
|
+ {
|
|
|
+ path0: new THREE.Vector3(4.441, 17.267, 3.614),
|
|
|
+ path1: new THREE.Vector3(5.041, 6.806, 3.614),
|
|
|
+ isSpread: true,
|
|
|
+ spreadDirection: 1, //
|
|
|
+ },
|
|
|
+ ];
|
|
|
+ const tubPositivePath = [
|
|
|
+ {
|
|
|
+ path0: new THREE.Vector3(7.441, 0.806, 3.614),
|
|
|
+ path1: new THREE.Vector3(44.583, 1.485, 3.614),
|
|
|
+ isSpread: false,
|
|
|
+ spreadDirection: 0, //
|
|
|
+ },
|
|
|
+ {
|
|
|
+ path0: new THREE.Vector3(44.583, 1.485, 3.614),
|
|
|
+ path1: new THREE.Vector3(45.741, 5.364, 3.614),
|
|
|
+ isSpread: false,
|
|
|
+ spreadDirection: 0,
|
|
|
+ },
|
|
|
+ {
|
|
|
+ path0: new THREE.Vector3(45.741, 5.364, 3.614),
|
|
|
+ path1: new THREE.Vector3(47.741, 17.267, 3.614),
|
|
|
+ isSpread: true,
|
|
|
+ spreadDirection: 1, // 1是由小变大(出),-1是由大变小(进)
|
|
|
+ },
|
|
|
+ ];
|
|
|
+ const tubInversePath = [
|
|
|
+ {
|
|
|
+ path0: new THREE.Vector3(47.741, 17.267, 3.614),
|
|
|
+ path1: new THREE.Vector3(45.741, 5.364, 3.614),
|
|
|
+ isSpread: true,
|
|
|
+ spreadDirection: -1, //
|
|
|
+ },
|
|
|
+ {
|
|
|
+ path0: new THREE.Vector3(45.741, 5.364, 3.614),
|
|
|
+ path1: new THREE.Vector3(44.583, 1.485, 3.614),
|
|
|
+ isSpread: false,
|
|
|
+ spreadDirection: 0, //
|
|
|
+ },
|
|
|
+ {
|
|
|
+ path0: new THREE.Vector3(44.583, 1.485, 3.614),
|
|
|
+ path1: new THREE.Vector3(7.441, 0.806, 3.614),
|
|
|
+ isSpread: false,
|
|
|
+ spreadDirection: 0, // 1是由小变大,-1是由大变小
|
|
|
+ },
|
|
|
+ ];
|
|
|
+ const getPathPoint = () => {
|
|
|
+ this.arrowMesh = this.group?.getObjectByName('arrow');
|
|
|
+ if (this.arrowMesh) return;
|
|
|
+ pathPoints.push(new THREE.Vector3(16.441, 1.485, 2.614), new THREE.Vector3(35.583, 1.485, 2.614));
|
|
|
+ const pathPointList = new PathPointList();
|
|
|
+ const up = new THREE.Vector3(0, 0, 1);
|
|
|
+ pathPointList.set(pathPoints, 0, 0, up, false);
|
|
|
+ const geometry = new PathGeometry(pathPoints.length, false);
|
|
|
+ geometry.update(pathPointList, {
|
|
|
+ width: 2,
|
|
|
+ arrow: false,
|
|
|
+ });
|
|
|
+
|
|
|
+ this.arrowMesh = new THREE.Mesh(geometry, this.material);
|
|
|
+ this.arrowMesh.name = 'arrow';
|
|
|
+ this.group?.add(this.arrowMesh);
|
|
|
+ };
|
|
|
+
|
|
|
+ if (deviceType === 'front') {
|
|
|
+ smoke = this.frontSmoke;
|
|
|
+ } else if (deviceType === 'back') {
|
|
|
+ smoke = this.backSmoke;
|
|
|
+ } else {
|
|
|
+ smoke = this.centerSmoke;
|
|
|
+ }
|
|
|
+ switch (smokeDirection) {
|
|
|
+ case 'tubPositivePath': // 风筒正
|
|
|
+ smoke.setPath(tubPositivePath);
|
|
|
+ if (this.direction !== 1) {
|
|
|
+ this.direction = 1;
|
|
|
+ this.airTexture.repeat.x = 1;
|
|
|
+ }
|
|
|
+ break;
|
|
|
+ case 'tubInversePath': // 风筒反
|
|
|
+ smoke.setPath(tubInversePath);
|
|
|
+ if (this.direction !== -1) {
|
|
|
+ this.direction = -1;
|
|
|
+ this.airTexture.repeat.x = -1;
|
|
|
+ }
|
|
|
+ break;
|
|
|
+ case 'windowPositivePath': // 风窗正
|
|
|
+ smoke.setPath(windowPositivePath);
|
|
|
+ if (this.direction !== 1) {
|
|
|
+ this.direction = 1;
|
|
|
+ this.airTexture.repeat.x = 1;
|
|
|
+ }
|
|
|
+ break;
|
|
|
+ case 'windowInversePath': // 风窗反
|
|
|
+ smoke.setPath(windowInversePath);
|
|
|
+ if (this.direction !== -1) {
|
|
|
+ this.direction = -1;
|
|
|
+ this.airTexture.repeat.x = -1;
|
|
|
+ }
|
|
|
+ break;
|
|
|
+ }
|
|
|
+ getPathPoint();
|
|
|
+ if (deviceType === 'front') {
|
|
|
+ if (this.arrowMesh && this.arrowMesh.position.z !== 2.31) this.arrowMesh.position.set(-6.48, 5.51, 13.25);
|
|
|
+ } else if (deviceType === 'center') {
|
|
|
+ if (this.arrowMesh && this.arrowMesh.position.z !== -12.99) this.arrowMesh.position.set(-6.48, 5.51, -0.02);
|
|
|
+ } else {
|
|
|
+ if (this.arrowMesh && this.arrowMesh.position.z !== -12.99) this.arrowMesh.position.set(-6.48, 5.51, -14.67);
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ /* 播放气流动画 */
|
|
|
+ /**
|
|
|
+ *
|
|
|
+ * @param controlType // 设备控制类型
|
|
|
+ * @param deviceType //前后风机
|
|
|
+ * @param frequencyVal // 风机运行频率
|
|
|
+ * @param state // 打开、关闭状态
|
|
|
+ */
|
|
|
+ async playSmoke(controlType, deviceType, frequencyVal, state, smokeDirection) {
|
|
|
+ if (frequencyVal) {
|
|
|
+ this.resetSmokeParam(deviceType, frequencyVal);
|
|
|
+ }
|
|
|
+ if (controlType === 'startSmoke') {
|
|
|
+ if (state === 'stop') {
|
|
|
+ await this.closeDevice(deviceType);
|
|
|
+ } else {
|
|
|
+ // 开启时需要设置方向
|
|
|
+ await this.openDevice(deviceType, smokeDirection, frequencyVal);
|
|
|
+ }
|
|
|
+ } else if (controlType === 'changeDirection') {
|
|
|
+ // 改变扇叶转动方向、反风
|
|
|
+ this.startGearAnimation(deviceType, 'changeDirection', smokeDirection, frequencyVal);
|
|
|
+ let smoke;
|
|
|
+ if (deviceType === 'front') {
|
|
|
+ smoke = this.frontSmoke;
|
|
|
+ } else if (deviceType === 'center') {
|
|
|
+ smoke = this.centerSmoke;
|
|
|
+ } else {
|
|
|
+ smoke = this.backSmoke;
|
|
|
+ }
|
|
|
+ if (smoke && smoke.frameId) {
|
|
|
+ await smoke.stopSmoke();
|
|
|
+ await this.setSmokeDirection(deviceType, smokeDirection);
|
|
|
+ smoke.startSmoke();
|
|
|
+ }
|
|
|
+ } else if (controlType === 'frequency') {
|
|
|
+ this.startGearAnimation(deviceType, 'frequency', smokeDirection, frequencyVal);
|
|
|
+ } else if (controlType === 'initiatePlay') {
|
|
|
+ this.openDevice(deviceType, smokeDirection, frequencyVal, 0);
|
|
|
+ } else if (controlType === 'changeSmoke') {
|
|
|
+ //
|
|
|
+ }
|
|
|
+ }
|
|
|
+ stopSmoke() {
|
|
|
+ this.closeDevice('front', false);
|
|
|
+ this.closeDevice('back', false);
|
|
|
+ this.closeDevice('center', false);
|
|
|
+ }
|
|
|
+
|
|
|
+ /* 打开或关闭蝶阀 */
|
|
|
+ openOrCloseValve(deviceType, flag, duration = 3) {
|
|
|
+ const ztfjGroup = this.group?.getObjectByName('ztfj');
|
|
|
+ return new Promise((resolve) => {
|
|
|
+ let diefa;
|
|
|
+ if (deviceType == 'front') {
|
|
|
+ diefa = ztfjGroup?.getObjectByName('butterfly_valve001') as THREE.Mesh;
|
|
|
+ } else if (deviceType == 'center') {
|
|
|
+ diefa = ztfjGroup?.getObjectByName('butterfly_valve001') as THREE.Mesh;
|
|
|
+ } else {
|
|
|
+ diefa = ztfjGroup?.getObjectByName('butterfly_valve002') as THREE.Mesh;
|
|
|
+ }
|
|
|
+ let rotationY;
|
|
|
+ if (flag == 'open') {
|
|
|
+ rotationY = 0;
|
|
|
+ } else {
|
|
|
+ rotationY = Math.PI / 2;
|
|
|
+ }
|
|
|
+ if (diefa) {
|
|
|
+ gsap.to(diefa.rotation, {
|
|
|
+ y: rotationY,
|
|
|
+ duration: duration,
|
|
|
+ ease: 'none',
|
|
|
+ onComplete: function () {
|
|
|
+ resolve(null);
|
|
|
+ },
|
|
|
+ });
|
|
|
+ }
|
|
|
+ });
|
|
|
+ }
|
|
|
+
|
|
|
+ /* 风流调频, 范围1-50 */
|
|
|
+ // opacityFactor (0.4 300)
|
|
|
+ // life 最小 300, 最大 50
|
|
|
+ // speedFactor 最大0, 最小100
|
|
|
+ resetSmokeParam(deviceType, frequency, duration = 5) {
|
|
|
+ if (frequency < 1) frequency = 1;
|
|
|
+ if (frequency > 50) frequency = 50;
|
|
|
+ let smoke;
|
|
|
+ if (deviceType === 'front') {
|
|
|
+ smoke = this.frontSmoke;
|
|
|
+ } else if (deviceType === 'center') {
|
|
|
+ smoke = this.centerSmoke;
|
|
|
+ } else {
|
|
|
+ smoke = this.backSmoke;
|
|
|
+ }
|
|
|
+ const opacityFactor = (frequency / 50) * 0.8;
|
|
|
+ duration = (Number(Math.abs(smoke.opacityFactor - opacityFactor).toFixed(1)) / 0.8) * 5;
|
|
|
+ const life = (-250 / 50) * frequency + 300;
|
|
|
+ gsap.to(smoke, {
|
|
|
+ opacityFactor: opacityFactor,
|
|
|
+ life: life,
|
|
|
+ duration: duration,
|
|
|
+ ease: 'easeInCirc',
|
|
|
+ overwrite: true,
|
|
|
+ });
|
|
|
+ }
|
|
|
+
|
|
|
+ /* 显示电机 */
|
|
|
+ lookMotor(deviceType, flag, duration = 5) {
|
|
|
+ return new Promise((resolve) => {
|
|
|
+ const mainWindLj3 = this.group?.getObjectByName('mainWindLj3');
|
|
|
+ const fengji = mainWindLj3?.getObjectByName('FengJi_SanFengTong');
|
|
|
+ const fengji1 = fengji?.getObjectByName('Feng1_1');
|
|
|
+ const fengji2 = fengji?.getObjectByName('Feng2_1');
|
|
|
+ const fengji3 = fengji?.getObjectByName('Feng3_2');
|
|
|
+
|
|
|
+ let mesh, mesh1, mesh2, mesh3, motorGroup;
|
|
|
+ mesh1 = fengji1?.getObjectByName('Feng1_97'); //前
|
|
|
+ mesh2 = fengji2?.getObjectByName('Feng2_94'); //中
|
|
|
+ mesh3 = fengji3?.getObjectByName('Feng1_97'); //后
|
|
|
+ if (deviceType == 'front') {
|
|
|
+ mesh = mesh1;
|
|
|
+ motorGroup = this.motorGroup1;
|
|
|
+ } else if (deviceType == 'center') {
|
|
|
+ mesh = mesh2;
|
|
|
+ motorGroup = this.motorGroup2;
|
|
|
+ } else {
|
|
|
+ mesh = mesh3;
|
|
|
+ motorGroup = this.motorGroup3;
|
|
|
+ }
|
|
|
+ if (mesh && motorGroup) {
|
|
|
+ if (flag == 'open') {
|
|
|
+ mesh.material.depthWrite = false;
|
|
|
+ mesh.material.depthTest = false;
|
|
|
+
|
|
|
+ motorGroup.visible = true;
|
|
|
+ gsap.to(mesh.material, {
|
|
|
+ opacity: 0.1,
|
|
|
+ duration: duration,
|
|
|
+ overwrite: true,
|
|
|
+ onComplete: function () {
|
|
|
+ // mesh.material.color = '#000';
|
|
|
+ resolve(null);
|
|
|
+ },
|
|
|
+ });
|
|
|
+ } else {
|
|
|
+ const opacity = mesh.material.opacity;
|
|
|
+ Object.assign(mesh.material, this.oldMaterial, { opacity: opacity });
|
|
|
+ mesh.material.depthWrite = true;
|
|
|
+ mesh.material.depthTest = true;
|
|
|
+ gsap.to(mesh.material, {
|
|
|
+ opacity: 1,
|
|
|
+ duration: 1,
|
|
|
+ overwrite: true,
|
|
|
+ onComplete: function () {
|
|
|
+ resolve(null);
|
|
|
+ },
|
|
|
+ });
|
|
|
+ }
|
|
|
+ }
|
|
|
+ });
|
|
|
+ }
|
|
|
+
|
|
|
+ /* 齿轮转动动画 1 - 50 最大3 */
|
|
|
+ startGearAnimation(deviceType, flag, smokeDirection, frequencyVal, duration = 8) {
|
|
|
+ let gearObj, gearDirection;
|
|
|
+ if (deviceType === 'front') {
|
|
|
+ gearObj = this.gearFront;
|
|
|
+ } else if (deviceType === 'center') {
|
|
|
+ gearObj = this.gearCenter;
|
|
|
+ } else {
|
|
|
+ gearObj = this.gearBack;
|
|
|
+ }
|
|
|
+ if (smokeDirection === 'tubPositivePath') {
|
|
|
+ gearDirection = 1;
|
|
|
+ } else if (smokeDirection === 'tubInversePath') {
|
|
|
+ gearDirection = -1;
|
|
|
+ }
|
|
|
+ if (frequencyVal) {
|
|
|
+ const endGearRotateFactor = (3 / 50) * frequencyVal;
|
|
|
+ duration = (8 / 3) * Math.abs(gearObj.endGearRotateFactor - endGearRotateFactor);
|
|
|
+ gearObj.endGearRotateFactor = endGearRotateFactor;
|
|
|
+ }
|
|
|
+
|
|
|
+ const gearAnimation = () => {
|
|
|
+ gsap.to(gearObj, {
|
|
|
+ gearRotateFactor: gearObj.endGearRotateFactor,
|
|
|
+ duration: duration,
|
|
|
+ ease: 'easeInCubic',
|
|
|
+ repeat: 0,
|
|
|
+ overwrite: true,
|
|
|
+ });
|
|
|
+
|
|
|
+ const clock = new THREE.Clock(); // 时钟
|
|
|
+ const h = () => {
|
|
|
+ if (gearObj.gear1 && gearObj.gear2) {
|
|
|
+ gearObj.gearFrameId = requestAnimationFrame(h);
|
|
|
+
|
|
|
+ const dt = clock.getDelta();
|
|
|
+ gearObj.gear1.rotation.x += dt * gearObj.gearRotateFactor * gearObj.gear1Direction;
|
|
|
+ gearObj.gear2.rotation.x += dt * gearObj.gearRotateFactor * gearObj.gear2Direction;
|
|
|
+ }
|
|
|
+ };
|
|
|
+ h();
|
|
|
+ };
|
|
|
+ if (flag === 'changeDirection') {
|
|
|
+ if (gearDirection == -1 * gearObj.gear1Direction) {
|
|
|
+ // 齿轮正在转,需要停止后再反方向转
|
|
|
+ gsap.to(gearObj, {
|
|
|
+ gearRotateFactor: 0,
|
|
|
+ duration: duration,
|
|
|
+ ease: 'easeInCubic',
|
|
|
+ repeat: 0,
|
|
|
+ onComplete: function () {
|
|
|
+ window.cancelAnimationFrame(gearObj.gearFrameId);
|
|
|
+ gearObj.gearFrameId = undefined;
|
|
|
+ gearObj.gear1Direction = -1 * gearObj.gear1Direction;
|
|
|
+ gearObj.gear2Direction = -1 * gearObj.gear2Direction;
|
|
|
+ gearAnimation();
|
|
|
+ },
|
|
|
+ });
|
|
|
+ }
|
|
|
+ } else if (flag === 'open') {
|
|
|
+ gearObj.gear1Direction = gearDirection;
|
|
|
+ gearObj.gear2Direction = -1 * gearDirection;
|
|
|
+ gearAnimation();
|
|
|
+ } else if (flag === 'close') {
|
|
|
+ gsap.to(gearObj, {
|
|
|
+ gearRotateFactor: 0,
|
|
|
+ duration: duration,
|
|
|
+ ease: 'easeInCubic',
|
|
|
+ repeat: 0,
|
|
|
+ overwrite: true,
|
|
|
+ onComplete: function () {
|
|
|
+ window.cancelAnimationFrame(gearObj.gearFrameId);
|
|
|
+ gearObj.gearFrameId = undefined;
|
|
|
+ },
|
|
|
+ });
|
|
|
+ } else if (flag === 'frequency') {
|
|
|
+ gsap.to(gearObj, {
|
|
|
+ gearRotateFactor: gearObj.endGearRotateFactor,
|
|
|
+ duration: duration,
|
|
|
+ ease: 'easeInCubic',
|
|
|
+ repeat: 0,
|
|
|
+ overwrite: true,
|
|
|
+ });
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ /* 初始化口上面的气体 */
|
|
|
+ initSmokeMass() {
|
|
|
+ if (!this.frontSmoke) {
|
|
|
+ this.frontSmoke = new Smoke('/model/img/texture-smoke.png', '#ffffff', 0, 0.4, 1.8, 100);
|
|
|
+ }
|
|
|
+ if (!this.centerSmoke) {
|
|
|
+ this.centerSmoke = new Smoke('/model/img/texture-smoke.png', '#ffffff', 0, 0.4, 1.8, 100);
|
|
|
+ }
|
|
|
+ if (!this.backSmoke) {
|
|
|
+ this.backSmoke = new Smoke('/model/img/texture-smoke.png', '#ffffff', 0, 0.4, 1.8, 100);
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ /* 设置气流位置 */
|
|
|
+ async setSmokePosition() {
|
|
|
+ if (this.frontSmoke) {
|
|
|
+ await this.frontSmoke.setPoints();
|
|
|
+ this.frontSmoke.points.name = 'frontSmoke';
|
|
|
+ this.group?.add(this.frontSmoke.points);
|
|
|
+ this.frontSmoke.points.position.set(-11.75, 4.15, 14.39);
|
|
|
+ }
|
|
|
+ if (this.centerSmoke) {
|
|
|
+ await this.centerSmoke.setPoints();
|
|
|
+ this.centerSmoke.points.name = 'centerSmoke';
|
|
|
+ this.group?.add(this.centerSmoke.points);
|
|
|
+ this.centerSmoke.points.position.set(-11.75, 4.15, -0.69);
|
|
|
+ }
|
|
|
+ if (this.backSmoke) {
|
|
|
+ await this.backSmoke.setPoints();
|
|
|
+ this.backSmoke.points.name = 'backSmoke';
|
|
|
+ this.group?.add(this.backSmoke.points);
|
|
|
+ this.backSmoke.points.position.set(-11.75, 4.15, -15.51);
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ /** 初始化电机 */
|
|
|
+ async initMotor() {
|
|
|
+ const mainWindLj3 = this.group?.getObjectByName('mainWindLj3');
|
|
|
+ const fengji = mainWindLj3?.getObjectByName('FengJi_SanFengTong');
|
|
|
+ // 前电机
|
|
|
+ this.motorGroup1 = fengji?.getObjectByName('Feng1_1');
|
|
|
+ this.gearFront.gear1 = this.motorGroup1?.getObjectByName('Feng1_33');
|
|
|
+ this.gearFront.gear2 = this.motorGroup1?.getObjectByName('Feng1_44');
|
|
|
+
|
|
|
+ // 中间电机
|
|
|
+ this.motorGroup2 = fengji?.getObjectByName('Feng2_1');
|
|
|
+ this.gearCenter.gear1 = this.motorGroup1?.getObjectByName('Feng2_10');
|
|
|
+ this.gearCenter.gear2 = this.motorGroup1?.getObjectByName('Feng2_29');
|
|
|
+
|
|
|
+ // 后电机
|
|
|
+ this.motorGroup3 = fengji?.getObjectByName('Feng3_2');
|
|
|
+ this.gearBack.gear1 = this.motorGroup1?.getObjectByName('Feng3_10');
|
|
|
+ this.gearBack.gear2 = this.motorGroup1?.getObjectByName('Feng3_28');
|
|
|
+ }
|
|
|
+
|
|
|
+ mountedThree() {
|
|
|
+ this.group = new THREE.Group();
|
|
|
+ return new Promise(async (resolve) => {
|
|
|
+ this.model.setGLTFModel(['bg1', 'mainWindLj3'], this.group).then(async () => {
|
|
|
+ // this.group = gltf[0];
|
|
|
+
|
|
|
+ console.log(this.group);
|
|
|
+ this.group?.position.set(-0.44, 19.88, 22.37);
|
|
|
+ const mainWindLj3 = this.group?.getObjectByName('mainWindLj3') as THREE.Group;
|
|
|
+ mainWindLj3.position.set(0, 1.48, 2.94);
|
|
|
+ mainWindLj3.scale.set(2.5, 2.5, 2.5);
|
|
|
+ this.initSmokeMass();
|
|
|
+ await this.setSmokePosition();
|
|
|
+
|
|
|
+ const ztfjGroup = mainWindLj3?.getObjectByName('FengJi_SanFengTong');
|
|
|
+ const fegnji = ztfjGroup?.getObjectByName('Feng1_1');
|
|
|
+
|
|
|
+ const mesh = fegnji?.getObjectByName('Feng1_97') as THREE.Mesh; //前
|
|
|
+ if (mesh && mesh.material) this.oldMaterial = mesh.material as THREE.MeshStandardMaterial;
|
|
|
+ await this.initMotor();
|
|
|
+ resolve(null);
|
|
|
+
|
|
|
+ const loader = new THREE.TextureLoader();
|
|
|
+ this.airTexture = loader.load('/model/img/air.png');
|
|
|
+ this.airTexture.wrapS = THREE.RepeatWrapping;
|
|
|
+ this.airTexture.repeat.set(1, 1.2);
|
|
|
+ this.airTexture.offset.y = 0;
|
|
|
+ this.airTexture.matrix.scale(0.5, 0.5);
|
|
|
+ this.airTexture.needsUpdate = true;
|
|
|
+ this.material = new THREE.MeshBasicMaterial({
|
|
|
+ map: this.airTexture,
|
|
|
+ transparent: true,
|
|
|
+ side: THREE.FrontSide,
|
|
|
+ });
|
|
|
+ this.clock.start();
|
|
|
+ });
|
|
|
+ });
|
|
|
+ }
|
|
|
+
|
|
|
+ destroy() {
|
|
|
+ if (this.frontSmoke) this.frontSmoke.clearSmoke();
|
|
|
+ if (this.centerSmoke) this.centerSmoke.clearSmoke();
|
|
|
+ if (this.backSmoke) this.backSmoke.clearSmoke();
|
|
|
+
|
|
|
+ this.model.clearGroup(this.motorGroup1);
|
|
|
+ this.model.clearGroup(this.motorGroup2);
|
|
|
+ this.model.clearGroup(this.group);
|
|
|
+
|
|
|
+ this.motorGroup1 = undefined;
|
|
|
+ this.motorGroup2 = undefined;
|
|
|
+
|
|
|
+ this.gearFront.gear1 = undefined;
|
|
|
+ this.gearFront.gear2 = undefined;
|
|
|
+
|
|
|
+ this.gearCenter.gear1 = undefined;
|
|
|
+ this.gearCenter.gear2 = undefined;
|
|
|
+
|
|
|
+ this.gearBack.gear1 = undefined;
|
|
|
+ this.gearBack.gear2 = undefined;
|
|
|
+
|
|
|
+ this.frontSmoke = undefined;
|
|
|
+ this.centerSmoke = undefined;
|
|
|
+ this.backSmoke = undefined;
|
|
|
+
|
|
|
+ this.model = undefined;
|
|
|
+ this.group = undefined;
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+export default mainWindLj3;
|