mainWind.xj.threejs.ts 23 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730
  1. import * as THREE from 'three';
  2. import { CSS3DObject } from 'three/examples/jsm/renderers/CSS3DRenderer.js';
  3. import Smoke from '/@/views/vent/comment/threejs/Smoke';
  4. import { renderVideo } from '/@/utils/threejs/util';
  5. import gsap from 'gsap';
  6. class mainXjWindRect {
  7. model;
  8. modelName = 'mainXjWindRect';
  9. group: THREE.Group | null = null; // 主通风机场景
  10. motorGroup1: THREE.Group | null = null; //电机
  11. motorGroup2: THREE.Group | null = null; //电机
  12. gearFront = {
  13. gear1: null, //扇叶
  14. gear2: null, //扇叶
  15. gear1Direction: -1,
  16. gear2Direction: 1,
  17. gearFrameId: undefined,
  18. gearRotateFactor: 0.5,
  19. endGearRotateFactor: 3,
  20. };
  21. gearBack = {
  22. gear1: null, //扇叶
  23. gear2: null, //扇叶
  24. gear1Direction: -1, // 扇叶转动方向
  25. gear2Direction: 1, // 扇叶转动方向
  26. gearFrameId: undefined,
  27. gearRotateFactor: 0.5, // 扇叶转动因素
  28. endGearRotateFactor: 3, // 扇叶最终转动速度因素
  29. };
  30. oldMaterial: THREE.Material = new THREE.MeshStandardMaterial();
  31. // smoke;
  32. frontSmoke: Smoke | null = null; // 前面风流对象
  33. backSmoke: Smoke | null = null; // 后面风流对象
  34. player1; // 视频播放器
  35. playerStartClickTime1 = new Date().getTime();
  36. frontWindowGroup;
  37. backWindowGroup;
  38. windowAngle = 0;
  39. fbmAnimationClip: THREE.AnimationClip | null = null;
  40. fbmMixers: THREE.AnimationMixer | null = null;
  41. fbmOpenAction: THREE.AnimationAction | null = null;
  42. constructor(model, playerVal1) {
  43. this.model = model;
  44. this.player1 = playerVal1;
  45. }
  46. // 添加 cssObject
  47. addCssText() {
  48. if (!this.group) {
  49. return;
  50. }
  51. const ztfjGroup = this.group.getObjectByName('ztfj');
  52. if (!this.group.getObjectByName('monitorText1')) {
  53. const worldPosition = new THREE.Vector3();
  54. ztfjGroup?.getObjectByName('FengJiWaiKe_1')?.getWorldPosition(worldPosition);
  55. const element = document.getElementById('inputBox') as HTMLElement;
  56. if (element) {
  57. const mainCSS3D = new CSS3DObject(element);
  58. mainCSS3D.name = 'monitorText1';
  59. mainCSS3D.scale.set(0.09, 0.09, 0.09);
  60. mainCSS3D.position.set(worldPosition.x + 34, worldPosition.y - 35, worldPosition.z - 35);
  61. mainCSS3D.lookAt(worldPosition.x + 34, worldPosition.y - 30, worldPosition.z + 2);
  62. this.group.add(mainCSS3D);
  63. }
  64. }
  65. if (!this.group.getObjectByName('monitorText2')) {
  66. const worldPosition = new THREE.Vector3();
  67. ztfjGroup?.getObjectByName('FengJiWaiKe_2')?.getWorldPosition(worldPosition);
  68. const element = document.getElementById('inputBox1') as HTMLElement;
  69. if (element) {
  70. const mainCSS3D = new CSS3DObject(element);
  71. mainCSS3D.name = 'monitorText2';
  72. mainCSS3D.scale.set(0.09, 0.09, 0.09);
  73. mainCSS3D.position.set(worldPosition.x + 34, worldPosition.y - 35, worldPosition.z - 20);
  74. mainCSS3D.lookAt(worldPosition.x + 34, worldPosition.y - 30, worldPosition.z + 2);
  75. this.group.add(mainCSS3D);
  76. }
  77. }
  78. if (!this.group.getObjectByName('monitorText4')) {
  79. const worldPosition = new THREE.Vector3();
  80. const fbmGroup = this.group?.getObjectByName('fbm') as THREE.Group;
  81. if (fbmGroup) {
  82. fbmGroup?.getObjectByName('Box022')?.getWorldPosition(worldPosition);
  83. const element = document.getElementById('fbm') as HTMLElement;
  84. if (element) {
  85. const mainCSS3D = new CSS3DObject(element);
  86. mainCSS3D.name = 'monitorText4';
  87. mainCSS3D.scale.set(0.07, 0.07, 0.07);
  88. mainCSS3D.position.set(worldPosition.x + 20, worldPosition.y - 8, worldPosition.z - 20);
  89. mainCSS3D.lookAt(worldPosition.x + 20, worldPosition.y - 0, worldPosition.z + 2);
  90. this.group.add(mainCSS3D);
  91. }
  92. }
  93. }
  94. }
  95. clearCssText() {
  96. if (this.group) {
  97. const mainCSS3D1 = this.group.getObjectByName('monitorText2');
  98. const mainCSS3D2 = this.group.getObjectByName('monitorText3');
  99. if (mainCSS3D1) this.group.remove(mainCSS3D1);
  100. if (mainCSS3D2) this.group.remove(mainCSS3D2);
  101. }
  102. }
  103. addEcharts() {
  104. const echartsBox = document.getElementById('fan-echarts');
  105. if (echartsBox) {
  106. const canvasObj = echartsBox.getElementsByTagName('canvas')[0];
  107. // 将canvas 纹理转换为材质
  108. const echartsMap = new THREE.CanvasTexture(canvasObj); // 关键一步
  109. const echartsMaterial = new THREE.MeshBasicMaterial({
  110. map: echartsMap, // 设置纹理贴图
  111. transparent: true,
  112. side: THREE.FrontSide, // 这里是双面渲染的意思
  113. });
  114. echartsMaterial.blending = THREE.CustomBlending;
  115. const monitorPlane = this.group?.getObjectByName('monitorEcharts');
  116. if (monitorPlane) {
  117. monitorPlane.material = echartsMaterial;
  118. } else {
  119. const planeGeometry = new THREE.PlaneGeometry(17.6, 9.9); // 平面3维几何体PlaneGeometry
  120. const planeMesh = new THREE.Mesh(planeGeometry, echartsMaterial);
  121. planeMesh.name = 'monitorEcharts';
  122. planeMesh.scale.set(1, 1, 1);
  123. planeMesh.position.set(-47.38, 13.227, -21.79);
  124. this.group?.add(planeMesh);
  125. }
  126. }
  127. }
  128. initAnimation() {}
  129. startAnimation() {}
  130. /* 更新动画 */
  131. render() {
  132. if (!this.model) {
  133. return;
  134. }
  135. if (this.fbmMixers) this.fbmMixers?.update(1 / 25);
  136. }
  137. /* 点击风窗,风窗全屏 */
  138. mousedownModel(intersects: THREE.Intersection<THREE.Object3D<THREE.Event>>[]) {
  139. // 判断是否点击到视频
  140. intersects.find((intersect) => {
  141. const mesh = intersect.object;
  142. if (mesh.name === 'player1') {
  143. if (new Date().getTime() - this.playerStartClickTime1 < 400) {
  144. // 双击,视频放大
  145. if (this.player1) {
  146. this.player1.requestFullscreen();
  147. }
  148. }
  149. this.playerStartClickTime1 = new Date().getTime();
  150. return true;
  151. }
  152. return false;
  153. });
  154. }
  155. mouseUpModel() {}
  156. async setDeviceFrequency(deviceType, state, frequencyVal?) {
  157. // 调节频率
  158. if (frequencyVal) {
  159. this.resetSmokeParam(deviceType, frequencyVal, 0);
  160. }
  161. // this.openOrCloseValve(deviceType, state, 0);
  162. this.startGearAnimation(deviceType, state, '', 0);
  163. if (deviceType === 'front') {
  164. this.frontSmoke?.startSmoke();
  165. } else {
  166. this.backSmoke?.startSmoke();
  167. }
  168. setTimeout(() => {
  169. this.lookMotor(deviceType, state, 10);
  170. }, 2000);
  171. }
  172. async openDevice(deviceType, smokeDirection, frequencyVal, duration?) {
  173. if (smokeDirection) {
  174. this.setSmokeDirection(deviceType, smokeDirection);
  175. }
  176. let smoke;
  177. if (deviceType === 'front') {
  178. smoke = this.frontSmoke;
  179. } else {
  180. smoke = this.backSmoke;
  181. }
  182. if (!smoke.frameId) {
  183. await this.lookMotor(deviceType, 'open', duration);
  184. // await this.openOrCloseValve(deviceType, 'open', duration);
  185. this.startGearAnimation(deviceType, 'open', smokeDirection, frequencyVal, duration);
  186. smoke.startSmoke(duration);
  187. }
  188. }
  189. async closeDevice(deviceType, flag = true) {
  190. let smoke;
  191. if (deviceType === 'front') {
  192. smoke = this.frontSmoke;
  193. } else if (deviceType === 'back') {
  194. smoke = this.backSmoke;
  195. }
  196. if (smoke && smoke.frameId) {
  197. // console.log('风机关闭', deviceType);
  198. if (flag) {
  199. smoke.stopSmoke();
  200. // await this.openOrCloseValve(deviceType, 'close');
  201. this.startGearAnimation(deviceType, 'close', '', null);
  202. await this.lookMotor(deviceType, 'close');
  203. } else {
  204. smoke.stopSmoke(0);
  205. // await this.openOrCloseValve(deviceType, 'close', 0);
  206. this.startGearAnimation(deviceType, 'close', '', null, 0);
  207. await this.lookMotor(deviceType, 'close', 0);
  208. }
  209. }
  210. }
  211. async setSmokeDirection(deviceType, smokeDirection) {
  212. const windowPositivePath = [
  213. {
  214. path0: new THREE.Vector3(4.441, 20.267, 3.614),
  215. path1: new THREE.Vector3(5.041, 6.806, 3.614),
  216. isSpread: true,
  217. spreadDirection: -1, //
  218. },
  219. {
  220. path0: new THREE.Vector3(7.441, 0.806, 3.614),
  221. path1: new THREE.Vector3(41.583, 1.485, 3.614),
  222. isSpread: false,
  223. spreadDirection: 0, //
  224. },
  225. {
  226. path0: new THREE.Vector3(41.583, 1.485, 3.614),
  227. path1: new THREE.Vector3(42.741, 5.364, 3.614),
  228. isSpread: false,
  229. spreadDirection: 0,
  230. },
  231. {
  232. path0: new THREE.Vector3(42.741, 5.364, 3.614),
  233. path1: new THREE.Vector3(44.741, 17.267, 3.614),
  234. isSpread: true,
  235. spreadDirection: 1, // 1是由小变大(出),-1是由大变小(进)
  236. },
  237. ];
  238. const windowInversePath = [
  239. {
  240. path0: new THREE.Vector3(44.741, 17.267, 3.614),
  241. path1: new THREE.Vector3(42.741, 5.364, 3.614),
  242. isSpread: true,
  243. spreadDirection: -1, //
  244. },
  245. {
  246. path0: new THREE.Vector3(42.741, 5.364, 3.614),
  247. path1: new THREE.Vector3(41.583, 1.485, 3.614),
  248. isSpread: false,
  249. spreadDirection: 0, //
  250. },
  251. {
  252. path0: new THREE.Vector3(41.583, 1.485, 3.614),
  253. path1: new THREE.Vector3(7.441, 0.806, 3.614),
  254. isSpread: false,
  255. spreadDirection: 0, // 1是由小变大,-1是由大变小
  256. },
  257. {
  258. path0: new THREE.Vector3(4.441, 17.267, 3.614),
  259. path1: new THREE.Vector3(5.041, 6.806, 3.614),
  260. isSpread: true,
  261. spreadDirection: 1, //
  262. },
  263. ];
  264. const tubPositivePath = [
  265. {
  266. path0: new THREE.Vector3(7.441, 0.806, 3.614),
  267. path1: new THREE.Vector3(44.583, 1.485, 3.614),
  268. isSpread: false,
  269. spreadDirection: 0, //
  270. },
  271. {
  272. path0: new THREE.Vector3(44.583, 1.485, 3.614),
  273. path1: new THREE.Vector3(45.741, 5.364, 3.614),
  274. isSpread: false,
  275. spreadDirection: 0,
  276. },
  277. {
  278. path0: new THREE.Vector3(45.741, 5.364, 3.614),
  279. path1: new THREE.Vector3(47.741, 17.267, 3.614),
  280. isSpread: true,
  281. spreadDirection: 1, // 1是由小变大(出),-1是由大变小(进)
  282. },
  283. ];
  284. const tubInversePath = [
  285. {
  286. path0: new THREE.Vector3(47.741, 17.267, 3.614),
  287. path1: new THREE.Vector3(45.741, 5.364, 3.614),
  288. isSpread: true,
  289. spreadDirection: -1, //
  290. },
  291. {
  292. path0: new THREE.Vector3(45.741, 5.364, 3.614),
  293. path1: new THREE.Vector3(44.583, 1.485, 3.614),
  294. isSpread: false,
  295. spreadDirection: 0, //
  296. },
  297. {
  298. path0: new THREE.Vector3(44.583, 1.485, 3.614),
  299. path1: new THREE.Vector3(7.441, 0.806, 3.614),
  300. isSpread: false,
  301. spreadDirection: 0, // 1是由小变大,-1是由大变小
  302. },
  303. ];
  304. let smoke;
  305. if (deviceType === 'front') {
  306. smoke = this.frontSmoke;
  307. } else if (deviceType === 'back') {
  308. smoke = this.backSmoke;
  309. }
  310. switch (smokeDirection) {
  311. case 'tubPositivePath': // 风筒正
  312. smoke.setPath(tubPositivePath);
  313. break;
  314. case 'tubInversePath': // 风筒反
  315. smoke.setPath(tubInversePath);
  316. break;
  317. case 'windowPositivePath': // 风窗正
  318. smoke.setPath(windowPositivePath);
  319. break;
  320. case 'windowInversePath': // 风窗反
  321. smoke.setPath(windowInversePath);
  322. break;
  323. }
  324. }
  325. /* 播放气流动画 */
  326. /**
  327. *
  328. * @param controlType // 设备控制类型
  329. * @param deviceType //前后风机
  330. * @param frequencyVal // 风机运行频率
  331. * @param state // 打开、关闭状态
  332. */
  333. async playSmoke(controlType, deviceType, frequencyVal, state, smokeDirection) {
  334. if (frequencyVal) {
  335. this.resetSmokeParam(deviceType, frequencyVal);
  336. }
  337. if (controlType === 'startSmoke') {
  338. if (state === 'stop') {
  339. await this.closeDevice(deviceType);
  340. } else {
  341. // 开启时需要设置方向
  342. await this.openDevice(deviceType, smokeDirection, frequencyVal);
  343. }
  344. } else if (controlType === 'changeDirection') {
  345. // 改变扇叶转动方向、反风
  346. this.startGearAnimation(deviceType, 'changeDirection', smokeDirection, frequencyVal);
  347. let smoke;
  348. if (deviceType === 'front') {
  349. smoke = this.frontSmoke;
  350. } else {
  351. smoke = this.backSmoke;
  352. }
  353. if (smoke && smoke.frameId) {
  354. await smoke.stopSmoke();
  355. await this.setSmokeDirection(deviceType, smokeDirection);
  356. smoke.startSmoke();
  357. }
  358. } else if (controlType === 'frequency') {
  359. this.startGearAnimation(deviceType, 'frequency', smokeDirection, frequencyVal);
  360. } else if (controlType === 'initiatePlay') {
  361. this.openDevice(deviceType, smokeDirection, frequencyVal, 0);
  362. } else if (controlType === 'changeSmoke') {
  363. //
  364. }
  365. }
  366. stopSmoke() {
  367. this.closeDevice('front', false);
  368. this.closeDevice('back', false);
  369. }
  370. /* 打开或关闭蝶阀 */
  371. openOrCloseValve(deviceType, flag, duration = 3) {
  372. const ztfjGroup = this.group?.getObjectByName('ztfj')?.getObjectByName('WaiKe');
  373. return new Promise((resolve) => {
  374. let diefa;
  375. if (deviceType == 'front') {
  376. diefa = ztfjGroup?.getObjectByName('Cylinder1206') as THREE.Mesh;
  377. } else {
  378. diefa = ztfjGroup?.getObjectByName('Cylinder1041') as THREE.Mesh;
  379. }
  380. let rotationY;
  381. if (flag == 'open') {
  382. rotationY = 0;
  383. } else {
  384. rotationY = Math.PI / 2;
  385. }
  386. if (diefa) {
  387. gsap.to(diefa.rotation, {
  388. y: rotationY,
  389. duration: duration,
  390. ease: 'none',
  391. onComplete: function () {
  392. resolve(null);
  393. },
  394. });
  395. }
  396. });
  397. }
  398. /* 风流调频, 范围1-50 */
  399. // opacityFactor (0.4 300)
  400. // life 最小 300, 最大 50
  401. // speedFactor 最大0, 最小100
  402. resetSmokeParam(deviceType, frequency, duration = 5) {
  403. if (frequency < 1) frequency = 1;
  404. if (frequency > 50) frequency = 50;
  405. let smoke;
  406. if (deviceType === 'front') {
  407. smoke = this.frontSmoke;
  408. } else {
  409. smoke = this.backSmoke;
  410. }
  411. const opacityFactor = (frequency / 50) * 0.8;
  412. duration = (Number(Math.abs(smoke.opacityFactor - opacityFactor).toFixed(1)) / 0.8) * 5;
  413. const life = (-250 / 50) * frequency + 300;
  414. gsap.to(smoke, {
  415. opacityFactor: opacityFactor,
  416. life: life,
  417. duration: duration,
  418. ease: 'easeInCirc',
  419. overwrite: true,
  420. });
  421. }
  422. /* 显示电机 */
  423. lookMotor(deviceType, flag, duration = 5) {
  424. return new Promise((resolve) => {
  425. const ztfjGroup = this.group?.getObjectByName('ztfj');
  426. let fengJiWaiKeGoup1, fengJiWaiKeGoup2, mesh, mesh1, mesh2, motorGroup;
  427. fengJiWaiKeGoup1 = ztfjGroup?.getObjectByName('FengJiWaiKe_1'); //前
  428. fengJiWaiKeGoup2 = ztfjGroup?.getObjectByName('FengJiWaiKe_2'); //前
  429. mesh1 = fengJiWaiKeGoup1?.getObjectByName('transparent_shell02'); //前
  430. mesh2 = fengJiWaiKeGoup2?.getObjectByName('transparent_shell00'); //后
  431. if (deviceType == 'front') {
  432. mesh = mesh1;
  433. motorGroup = this.motorGroup2;
  434. } else {
  435. mesh = mesh2;
  436. motorGroup = this.motorGroup1;
  437. }
  438. if (mesh && motorGroup) {
  439. if (flag == 'open') {
  440. mesh.material.depthWrite = false;
  441. mesh.material.depthTest = false;
  442. motorGroup.visible = true;
  443. gsap.to(mesh.material, {
  444. opacity: 0.1,
  445. duration: duration,
  446. overwrite: true,
  447. onComplete: function () {
  448. // mesh.material.color = '#000';
  449. resolve(null);
  450. },
  451. });
  452. } else {
  453. const opacity = mesh.material.opacity;
  454. Object.assign(mesh.material, this.oldMaterial, { opacity: opacity });
  455. mesh.material.depthWrite = true;
  456. mesh.material.depthTest = true;
  457. gsap.to(mesh.material, {
  458. opacity: 1,
  459. duration: 1,
  460. overwrite: true,
  461. onComplete: function () {
  462. resolve(null);
  463. },
  464. });
  465. }
  466. }
  467. });
  468. }
  469. /* 齿轮转动动画 1 - 50 最大3 */
  470. startGearAnimation(deviceType, flag, smokeDirection, frequencyVal, duration = 8) {
  471. console.log(deviceType, flag);
  472. // debugger;
  473. let gearObj, gearDirection;
  474. if (deviceType === 'front') {
  475. gearObj = this.gearFront;
  476. } else {
  477. gearObj = this.gearBack;
  478. }
  479. if (smokeDirection === 'tubPositivePath') {
  480. gearDirection = 1;
  481. } else if (smokeDirection === 'tubInversePath') {
  482. gearDirection = -1;
  483. }
  484. if (frequencyVal) {
  485. const endGearRotateFactor = (3 / 50) * frequencyVal;
  486. duration = (8 / 3) * Math.abs(gearObj.endGearRotateFactor - endGearRotateFactor);
  487. gearObj.endGearRotateFactor = endGearRotateFactor;
  488. }
  489. const gearAnimation = () => {
  490. gsap.to(gearObj, {
  491. gearRotateFactor: gearObj.endGearRotateFactor,
  492. duration: duration,
  493. ease: 'easeInCubic',
  494. repeat: 0,
  495. overwrite: true,
  496. });
  497. const clock = new THREE.Clock(); // 时钟
  498. const h = () => {
  499. if (gearObj.gear1 && gearObj.gear2) {
  500. gearObj.gearFrameId = requestAnimationFrame(h);
  501. const dt = clock.getDelta();
  502. gearObj.gear1.rotation.x += dt * gearObj.gearRotateFactor * gearObj.gear1Direction;
  503. gearObj.gear2.rotation.x += dt * gearObj.gearRotateFactor * gearObj.gear2Direction;
  504. }
  505. };
  506. h();
  507. };
  508. if (flag === 'changeDirection') {
  509. if (gearDirection == -1 * gearObj.gear1Direction) {
  510. // 齿轮正在转,需要停止后再反方向转
  511. gsap.to(gearObj, {
  512. gearRotateFactor: 0,
  513. duration: duration,
  514. ease: 'easeInCubic',
  515. repeat: 0,
  516. onComplete: function () {
  517. window.cancelAnimationFrame(gearObj.gearFrameId);
  518. gearObj.gearFrameId = undefined;
  519. gearObj.gear1Direction = -1 * gearObj.gear1Direction;
  520. gearObj.gear2Direction = -1 * gearObj.gear2Direction;
  521. gearAnimation();
  522. },
  523. });
  524. }
  525. } else if (flag === 'open') {
  526. gearObj.gear1Direction = gearDirection;
  527. gearObj.gear2Direction = -1 * gearDirection;
  528. gearAnimation();
  529. } else if (flag === 'close') {
  530. gsap.to(gearObj, {
  531. gearRotateFactor: 0,
  532. duration: duration,
  533. ease: 'easeInCubic',
  534. repeat: 0,
  535. overwrite: true,
  536. onComplete: function () {
  537. window.cancelAnimationFrame(gearObj.gearFrameId);
  538. gearObj.gearFrameId = undefined;
  539. },
  540. });
  541. } else if (flag === 'frequency') {
  542. gsap.to(gearObj, {
  543. gearRotateFactor: gearObj.endGearRotateFactor,
  544. duration: duration,
  545. ease: 'easeInCubic',
  546. repeat: 0,
  547. overwrite: true,
  548. });
  549. }
  550. }
  551. /* 初始化口上面的气体 */
  552. initSmokeMass() {
  553. if (!this.frontSmoke) {
  554. this.frontSmoke = new Smoke('/model/img/texture-smoke.png', '#ffffff', 0, 0.38, 1.8, 100);
  555. }
  556. if (!this.backSmoke) {
  557. this.backSmoke = new Smoke('/model/img/texture-smoke.png', '#ffffff', 0, 0.38, 1.8, 100);
  558. }
  559. }
  560. /* 设置气流位置 */
  561. async setSmokePosition() {
  562. if (this.frontSmoke) {
  563. await this.frontSmoke.setPoints();
  564. this.frontSmoke.points.name = 'frontSmoke';
  565. this.group?.add(this.frontSmoke.points);
  566. // this.frontSmoke.points.position.set(-2.51, 2.51, 8.25);
  567. this.frontSmoke.points.position.set(3.18, 4.43, 2.31);
  568. }
  569. if (this.backSmoke) {
  570. await this.backSmoke.setPoints();
  571. this.backSmoke.points.name = 'backSmoke';
  572. this.group?.add(this.backSmoke.points);
  573. // this.backSmoke.points.position.set(-2.2, 3.13, -7.8);
  574. this.backSmoke.points.position.set(3.18, 4.36, -13.99);
  575. }
  576. }
  577. /** 初始化电机 */
  578. async initMotor() {
  579. // 前电机
  580. const motorGltf1 = await this.model.setGLTFModel('dj1');
  581. this.motorGroup1 = motorGltf1[0] as THREE.Group;
  582. this.motorGroup1?.position.set(10, 1, -6);
  583. // this.motorGroup1.visible = false;
  584. this.motorGroup1.traverse((item) => {
  585. if (item instanceof THREE.Object3D) {
  586. item.renderOrder = -1;
  587. if (item.name === 'fan_blade003') {
  588. // @ts-ignore
  589. this.gearBack.gear1 = item as THREE.Group;
  590. } else if (item.name === 'fan_blade005') {
  591. // @ts-ignore
  592. this.gearBack.gear2 = item as THREE.Group;
  593. }
  594. }
  595. });
  596. this.motorGroup1.renderOrder = -1;
  597. this.group?.add(this.motorGroup1);
  598. // 后电机
  599. const motorGltf2 = await this.model.setGLTFModel('dj2');
  600. this.motorGroup2 = motorGltf2[0] as THREE.Group;
  601. this.motorGroup2?.position.set(10, 1, -6);
  602. // this.motorGroup2.visible = false;
  603. this.motorGroup2.traverse((item) => {
  604. if (item instanceof THREE.Object3D) {
  605. item.renderOrder = -1;
  606. if (item.name === 'fan_blade007') {
  607. // @ts-ignore
  608. this.gearFront.gear1 = item as THREE.Group;
  609. } else if (item.name === 'fan_blade006') {
  610. // @ts-ignore
  611. this.gearFront.gear2 = item as THREE.Group;
  612. }
  613. }
  614. });
  615. this.motorGroup2.renderOrder = -1;
  616. this.group?.add(this.motorGroup2);
  617. }
  618. openOrCloseWindow(deviceType, flag) {
  619. const _this = this;
  620. let endAngle = 0,
  621. windowGroup;
  622. if (deviceType === 'front') {
  623. windowGroup = this.frontWindowGroup;
  624. }
  625. if (deviceType === 'back') {
  626. windowGroup = this.backWindowGroup;
  627. }
  628. if (flag == 'openWindow') {
  629. // 打开风窗
  630. endAngle = 1;
  631. } else {
  632. // 关闭风窗
  633. endAngle = 0;
  634. }
  635. if (windowGroup)
  636. gsap.to(this, {
  637. windowAngle: endAngle,
  638. duration: Math.abs(endAngle - this.windowAngle) * 10,
  639. ease: 'none',
  640. onUpdate: function () {
  641. windowGroup.children.forEach((mesh) => {
  642. mesh.rotation.z = _this.windowAngle;
  643. });
  644. },
  645. });
  646. }
  647. playAnimation(flag, duration?) {}
  648. mountedThree() {
  649. this.group = new THREE.Group();
  650. debugger;
  651. return new Promise(async (resolve) => {
  652. this.model.setGLTFModel('ztfj-xj').then(async (gltf) => {
  653. const ztfjModal = gltf[0].children[0];
  654. ztfjModal.name = 'ztfj';
  655. ztfjModal.position.set(4.64, 4.11, 1.52);
  656. this.group?.add(gltf[0].children[0]);
  657. // this.group?.position.set(4.77, 3.63, 0.63);
  658. this.group?.position.set(-0.44, 47.32, 22.37);
  659. this.initSmokeMass();
  660. await this.setSmokePosition();
  661. const ztfjGroup = this.group?.getObjectByName('ztfj');
  662. const fengJiWaiKeGoup1 = ztfjGroup?.getObjectByName('FengJiWaiKe_1'); //前
  663. const mesh = fengJiWaiKeGoup1?.getObjectByName('transparent_shell02'); //前
  664. if (mesh && mesh.material) this.oldMaterial = mesh.material as THREE.MeshStandardMaterial;
  665. await this.initMotor();
  666. resolve(null);
  667. });
  668. });
  669. }
  670. destroy() {
  671. this.frontSmoke.clearSmoke();
  672. this.backSmoke.clearSmoke();
  673. this.model.clearGroup(this.motorGroup1);
  674. this.model.clearGroup(this.motorGroup2);
  675. this.model.clearGroup(this.group);
  676. this.motorGroup1 = undefined;
  677. this.motorGroup2 = undefined;
  678. this.gearFront.gear1 = undefined;
  679. this.gearFront.gear2 = undefined;
  680. this.gearBack.gear1 = undefined;
  681. this.gearBack.gear2 = undefined;
  682. this.frontSmoke = undefined;
  683. this.backSmoke = undefined;
  684. this.model = undefined;
  685. this.group = undefined;
  686. }
  687. }
  688. export default mainXjWindRect;