mainWind.xj.threejs.ts 24 KB

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