window.threejs.ts 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408
  1. import * as THREE from 'three';
  2. import UseThree from '../../../../utils/threejs/useThree';
  3. import ddFc_5 from './dandaoFc.threejs'; // ddFc_5 单道-大窗2列扇叶
  4. import singleWindowXk from './dandaoFcXk.threejs';
  5. import ddFc_1 from './dandaoFcYjl.threejs'; // ddFc_1 单道_小窗两列扇叶
  6. import sdFc_1 from './shuangdaoFc.threejs'; // sdFc_1 双道-带小门
  7. import sdFc_3 from './shuangdaoFcBlt.threejs'; // sdFc_3 双道-带小门-小窗
  8. import sdFc_4 from './shuangdaoFcHj.threejs'; // sdFc_4 双道-带门-卷闸
  9. import sdFc_2 from './shuangdaoFcSw.threejs'; // sdFc_2 单道-带小门-2个窗
  10. import sdFc_5 from './shuangdaoFcYjl.threejs'; // sdFc_5 双道-小门(侧边下)-小窗(榆家梁)
  11. import ddFc_4 from './dandaoFcBd1.threejs'; // ddFc_2 单道-一个小窗两列扇叶
  12. import ddFc_2 from './dandaoFcBd2.threejs'; // ddFc_2 单道-一个小窗两列扇叶
  13. import { animateCamera } from '/@/utils/threejs/util';
  14. import useEvent from '../../../../utils/threejs/useEvent';
  15. import { getDictItemsByCode } from '/@/utils/dict';
  16. // import * as dat from 'dat.gui';
  17. // const gui = new dat.GUI();
  18. // gui.domElement.style = 'position:absolute;top:100px;left:10px;z-index:99999999999999';
  19. // 模型对象、 文字对象
  20. let model: UseThree,
  21. ddFc5: ddFc_5,
  22. ddFc1: ddFc_1,
  23. sdFc1: sdFc_1,
  24. sdFc3: sdFc_3,
  25. sdFc4: sdFc_4,
  26. sdFc2: sdFc_2,
  27. sdFc5: sdFc_5,
  28. ddFc2: ddFc_2,
  29. ddFc4: ddFc_4,
  30. singleWindowXkObj: singleWindowXk,
  31. group: THREE.Object3D,
  32. windowType = 'ddFc1';
  33. const rotationParam = {
  34. frontDeg0: 0, // 前门初始
  35. frontDeg1: 0, // 前门目标
  36. backDeg0: 0, // 后门初始
  37. backDeg1: 0, // 后门目标
  38. };
  39. const { mouseDownFn } = useEvent();
  40. // 初始化左右摇摆动画
  41. const startAnimation = () => {
  42. // 定义鼠标点击事件
  43. model.canvasContainer?.addEventListener('mousedown', mouseEvent.bind(null));
  44. model.canvasContainer?.addEventListener('pointerup', (event) => {
  45. event.stopPropagation();
  46. // 单道、 双道
  47. if (windowType === 'ddFc5' && ddFc5) {
  48. ddFc5.mouseUpModel.call(ddFc5);
  49. } else if (windowType === 'ddFc1' && ddFc1) {
  50. ddFc1.mouseUpModel.call(ddFc1);
  51. } else if (windowType === 'ddFc2' && ddFc2) {
  52. ddFc2.mouseUpModel.call(ddFc2);
  53. } else if (windowType === 'ddFc4' && ddFc4) {
  54. ddFc4.mouseUpModel.call(ddFc4);
  55. } else if (windowType === 'sdFc1' && sdFc1) {
  56. sdFc1.mouseUpModel.call(sdFc1);
  57. } else if (windowType === 'sdFc3' && sdFc3) {
  58. sdFc3.mouseUpModel.call(sdFc3);
  59. } else if (windowType === 'sdFc4' && sdFc4) {
  60. sdFc4.mouseUpModel.call(sdFc4);
  61. } else if (windowType === 'sdFc2' && sdFc2) {
  62. sdFc2.mouseUpModel.call(sdFc2);
  63. } else if (windowType === 'sdFc5' && sdFc5) {
  64. sdFc5.mouseUpModel.call(sdFc5);
  65. } else if (windowType === 'singleXkWindow' && singleWindowXkObj) {
  66. singleWindowXkObj.mouseUpModel.call(singleWindowXkObj);
  67. }
  68. });
  69. };
  70. // 鼠标点击、松开事件
  71. const mouseEvent = (event) => {
  72. if (event.button == 0) {
  73. mouseDownFn(model, group, event, (intersects) => {
  74. if (windowType === 'ddFc5' && ddFc5) {
  75. ddFc5.mousedownModel.call(ddFc5, intersects);
  76. } else if (windowType === 'ddFc1' && ddFc1) {
  77. ddFc1.mousedownModel.call(ddFc1, intersects);
  78. } else if (windowType === 'ddFc2' && ddFc2) {
  79. ddFc2.mousedownModel.call(ddFc2, intersects);
  80. } else if (windowType === 'ddFc4' && ddFc4) {
  81. ddFc4.mousedownModel.call(ddFc4, intersects);
  82. } else if (windowType === 'sdFc1' && sdFc1) {
  83. sdFc1.mousedownModel.call(sdFc1, intersects);
  84. } else if (windowType === 'sdFc3' && sdFc3) {
  85. sdFc3.mousedownModel.call(sdFc3, intersects);
  86. } else if (windowType === 'sdFc4' && sdFc4) {
  87. sdFc4.mousedownModel.call(sdFc4, intersects);
  88. } else if (windowType === 'sdFc2' && sdFc2) {
  89. sdFc2.mousedownModel.call(sdFc2, intersects);
  90. } else if (windowType === 'sdFc5' && sdFc5) {
  91. sdFc5.mousedownModel.call(sdFc5, intersects);
  92. } else if (windowType === 'singleXkWindow' && singleWindowXkObj) {
  93. singleWindowXkObj.mousedownModel.call(singleWindowXkObj, intersects);
  94. }
  95. });
  96. console.log('摄像头控制信息', model.orbitControls, model.camera);
  97. }
  98. };
  99. export const addMonitorText = (selectData) => {
  100. if (windowType === 'ddFc5' && ddFc5) {
  101. return ddFc5.addMonitorText.call(ddFc5, selectData);
  102. } else if (windowType === 'ddFc1' && ddFc1) {
  103. return ddFc1.addMonitorText.call(ddFc1, selectData);
  104. } else if (windowType === 'ddFc2' && ddFc2) {
  105. return ddFc2.addMonitorText.call(ddFc2, selectData);
  106. } else if (windowType === 'ddFc4' && ddFc4) {
  107. return ddFc4.addMonitorText.call(ddFc4, selectData);
  108. } else if (windowType === 'sdFc1' && sdFc1) {
  109. return sdFc1.addMonitorText.call(sdFc1, selectData);
  110. } else if (windowType === 'sdFc3' && sdFc3) {
  111. return sdFc3.addMonitorText.call(sdFc3, selectData);
  112. } else if (windowType === 'sdFc4' && sdFc4) {
  113. return sdFc4.addMonitorText.call(sdFc4, selectData);
  114. } else if (windowType === 'sdFc2' && sdFc2) {
  115. return sdFc2.addMonitorText.call(sdFc2, selectData);
  116. } else if (windowType === 'sdFc5' && sdFc5) {
  117. return sdFc5.addMonitorText.call(sdFc5, selectData);
  118. } else if (windowType === 'singleXkWindow' && singleWindowXkObj) {
  119. return singleWindowXkObj.addMonitorText.call(singleWindowXkObj, selectData);
  120. }
  121. };
  122. export function computePlay(data, maxarea, isFirst = false) {
  123. const isJz = data.windowModal == 'sdFc4';
  124. if (windowType === 'singleXkWindow') {
  125. const acosToAngle = (cosValue) => {
  126. cosValue = Math.max(Math.min(cosValue, 1), -1);
  127. // 计算角度
  128. return Math.asin(cosValue) * (180 / Math.PI);
  129. };
  130. const sina = Math.sqrt((Math.sin((78 * Math.PI) / 180) ** 2 * parseFloat(data.forntArea)) / parseFloat(maxarea));
  131. const angleInRadians = acosToAngle(sina);
  132. rotationParam.frontDeg1 = angleInRadians;
  133. if (!rotationParam.frontDeg1 && !rotationParam.backDeg1) {
  134. // 当返回值有误时默认关闭
  135. play(rotationParam, 0);
  136. } else {
  137. setTimeout(() => {
  138. play(rotationParam, 1);
  139. }, 0);
  140. }
  141. } else {
  142. if (data.OpenDegree || data.OpenDegree1 || data.OpenDegree2) {
  143. maxarea = 180;
  144. if (data.OpenDegree) {
  145. rotationParam.frontDeg0 = (180 / maxarea) * Number(isFirst ? 0 : data.OpenDegree);
  146. rotationParam.frontDeg1 = (180 / maxarea) * Number(data.OpenDegree) || 0;
  147. }
  148. if (data.OpenDegree1) {
  149. rotationParam.frontDeg0 = (180 / maxarea) * Number(isFirst ? 0 : data.OpenDegree1);
  150. rotationParam.frontDeg1 = (180 / maxarea) * Number(data.OpenDegree1) || 0;
  151. }
  152. if (data.OpenDegree2) {
  153. rotationParam.backDeg0 = (180 / maxarea) * Number(isFirst ? 0 : data.OpenDegree2);
  154. rotationParam.backDeg1 = (180 / maxarea) * Number(data.OpenDegree2) || 0;
  155. }
  156. } else {
  157. // 这里判断是扇叶模型还是卷闸模型,如果是卷闸模型时
  158. if (isJz) {
  159. rotationParam.frontDeg0 = 0;
  160. rotationParam.backDeg0 = 0;
  161. rotationParam.frontDeg1 = data.forntArea / maxarea;
  162. rotationParam.backDeg1 = data.rearArea / maxarea;
  163. } else {
  164. if (!maxarea) maxarea = 90;
  165. rotationParam.frontDeg0 = (90 / maxarea) * Number(isFirst ? 0 : data.forntArea);
  166. rotationParam.backDeg0 = (90 / maxarea) * Number(isFirst ? 0 : data.rearArea);
  167. rotationParam.frontDeg1 = (90 / maxarea) * Number(data.forntArea) || 0;
  168. rotationParam.backDeg1 = (90 / maxarea) * Number(data.rearArea) || 0;
  169. }
  170. }
  171. if (isJz) {
  172. play(1, { scaleY: data.frontArea / maxarea });
  173. play(2, { scaleY: data.rearArea / maxarea });
  174. play(3, { scaleY: data.frontArea3 / maxarea });
  175. play(4, { scaleY: data.frontArea4 / maxarea });
  176. } else {
  177. if (!rotationParam.frontDeg1 && !rotationParam.backDeg1) {
  178. // 当返回值有误时默认关闭
  179. play(rotationParam, 0);
  180. } else {
  181. if (data.nwindownum == 1 || data.nwindownum == 2) {
  182. setTimeout(() => {
  183. play(rotationParam, 1);
  184. }, 0);
  185. }
  186. if (data.nwindownum == 2) {
  187. setTimeout(() => {
  188. play(rotationParam, 2);
  189. }, 0);
  190. }
  191. }
  192. }
  193. }
  194. }
  195. export const play = (rotationParam, flag) => {
  196. if (windowType === 'ddFc5' && ddFc5) {
  197. return ddFc5.play.call(ddFc5, rotationParam, flag);
  198. } else if (windowType === 'ddFc1' && ddFc1) {
  199. return ddFc1.play.call(ddFc1, rotationParam, flag);
  200. } else if (windowType === 'ddFc2' && ddFc2) {
  201. return ddFc2.play.call(ddFc2, rotationParam, flag);
  202. } else if (windowType === 'ddFc4' && ddFc4) {
  203. return ddFc4.play.call(ddFc4, rotationParam, flag);
  204. } else if (windowType === 'sdFc1' && sdFc1) {
  205. return sdFc1.play.call(sdFc1, rotationParam, flag);
  206. } else if (windowType === 'sdFc3' && sdFc3) {
  207. return sdFc3.play.call(sdFc3, rotationParam, flag);
  208. } else if (windowType === 'sdFc4' && sdFc4) {
  209. return sdFc4.play.call(sdFc4, rotationParam, flag);
  210. } else if (windowType === 'sdFc2' && sdFc2) {
  211. return sdFc2.play.call(sdFc2, rotationParam, flag);
  212. } else if (windowType === 'sdFc5' && sdFc5) {
  213. return sdFc5.play.call(sdFc5, rotationParam, flag);
  214. } else if (windowType === 'singleXkWindow' && singleWindowXkObj) {
  215. return singleWindowXkObj.play.call(singleWindowXkObj, rotationParam, flag);
  216. }
  217. };
  218. // 切换风窗类型
  219. export const setModelType = (type) => {
  220. // if (!model || !model.scene) return;
  221. windowType = type;
  222. const windowConfigurations = {
  223. sdFc1: {
  224. render: sdFc1 ? () => sdFc1.render() : null,
  225. group: sdFc1 ? sdFc1.group : null,
  226. newP: { x: 66.257, y: 57.539, z: 94.313 },
  227. newT: { x: 0, y: 0, z: 0 },
  228. },
  229. ddFc5: {
  230. render: ddFc5 ? () => ddFc5.render() : null,
  231. group: ddFc5 ? ddFc5.group : null,
  232. newP: { x: 66.257, y: 57.539, z: 94.313 },
  233. newT: { x: 0, y: 0, z: 0 },
  234. },
  235. ddFc1: {
  236. render: ddFc1 ? () => ddFc1.render() : null,
  237. group: ddFc1 ? ddFc1.group : null,
  238. newP: { x: 34.294433107431956, y: 19.284123769585108, z: 47.717286013509835 },
  239. newT: { x: 12.311816240141978, y: -5.691930035759495, z: -5.57302688985693 },
  240. },
  241. ddFc2: {
  242. render: ddFc2 ? () => ddFc2.render() : null,
  243. group: ddFc2 ? ddFc2.group : null,
  244. newP: { x: 66.257, y: 57.539, z: 94.313 },
  245. newT: { x: 0, y: 0, z: 0 },
  246. },
  247. ddFc4: {
  248. render: ddFc4 ? () => ddFc4.render() : null,
  249. group: ddFc4 ? ddFc4.group : null,
  250. newP: { x: 66.257, y: 57.539, z: 94.313 },
  251. newT: { x: 0, y: 0, z: 0 },
  252. },
  253. sdFc3: {
  254. render: sdFc3 ? () => sdFc3.render() : null,
  255. group: sdFc3 ? sdFc3.group : null,
  256. newP: { x: 66.257, y: 57.539, z: 94.313 },
  257. newT: { x: 0, y: 0, z: 0 },
  258. },
  259. sdFc4: {
  260. render: sdFc4 ? () => sdFc4.render() : null,
  261. group: sdFc4 ? sdFc4.group : null,
  262. newP: { x: 66.257, y: 57.539, z: 94.313 },
  263. newT: { x: 0, y: 0, z: 0 },
  264. },
  265. sdFc2: {
  266. render: sdFc2 ? () => sdFc2.render() : null,
  267. group: sdFc2 ? sdFc2.group : null,
  268. newP: { x: 66.257, y: 57.539, z: 94.313 },
  269. newT: { x: 0, y: 0, z: 0 },
  270. },
  271. sdFc5: {
  272. render: sdFc5 ? () => sdFc5.render() : null,
  273. group: sdFc5 ? sdFc5.group : null,
  274. newP: { x: 34.294433107431956, y: 19.284123769585108, z: 47.717286013509835 },
  275. newT: { x: 12.311816240141978, y: -5.691930035759495, z: -5.57302688985693 },
  276. },
  277. singleXkWindow: {
  278. render: singleWindowXkObj ? () => singleWindowXkObj.render() : null,
  279. group: singleWindowXkObj ? singleWindowXkObj.group : null,
  280. newP: { x: 116.08531358656566, y: 81.45510733175816, z: 193.00752046594465 },
  281. newT: { x: 23.446366480086372, y: -12.335134633777185, z: -5.63294282643405 },
  282. },
  283. };
  284. const oldCameraPosition = { x: 100, y: 0, z: 10 };
  285. model.scene?.remove(group);
  286. function handleWindowType(windowType: string, model: any) {
  287. const config = windowConfigurations[windowType];
  288. if (config && config.group) {
  289. model.startAnimation = config.render;
  290. group = config.group;
  291. return new Promise((resolve) => {
  292. setTimeout(async () => {
  293. await animateCamera(oldCameraPosition, { x: 0, y: 0, z: 0 }, config.newP, config.newT, model);
  294. model.scene?.add(config.group);
  295. resolve(null);
  296. }, 1000);
  297. });
  298. } else {
  299. throw new Error(`Unsupported windowType: ${windowType}`);
  300. }
  301. }
  302. return handleWindowType(windowType, model);
  303. };
  304. export const mountedThree = () => {
  305. // const { sysOrgCode } = useGlobSetting();
  306. // const sysOrgCode = 'zmhjhzmy';
  307. return new Promise(async (resolve) => {
  308. model = new UseThree('#window3D');
  309. if (!model || !model.renderer || !model.camera) return;
  310. model.setEnvMap('royal_esplanade_1k.hdr');
  311. model.renderer.toneMappingExposure = 1.8;
  312. model.camera.position.set(100, 0, 1000);
  313. // 根据模型类型判断要初始化哪些模型
  314. const dictCodes = getDictItemsByCode('windowModalType');
  315. for (let i = 0; i < dictCodes.length; i++) {
  316. const dict = dictCodes[i];
  317. switch (dict.value) {
  318. case 'sdFc1':
  319. sdFc1 = new sdFc_1(model);
  320. await sdFc1.mountedThree();
  321. break;
  322. case 'ddFc5':
  323. ddFc5 = new ddFc_5(model);
  324. await ddFc5.mountedThree();
  325. break;
  326. case 'ddFc1':
  327. ddFc1 = new ddFc_1(model);
  328. await ddFc1.mountedThree();
  329. break;
  330. case 'ddFc2':
  331. ddFc2 = new ddFc_2(model);
  332. await ddFc2.mountedThree();
  333. break;
  334. case 'ddFc4':
  335. ddFc4 = new ddFc_4(model);
  336. await ddFc4.mountedThree();
  337. break;
  338. case 'sdFc3':
  339. sdFc3 = new sdFc_3(model);
  340. await sdFc3.mountedThree();
  341. break;
  342. case 'sdFc4':
  343. sdFc4 = new sdFc_4(model);
  344. await sdFc4.mountedThree();
  345. break;
  346. case 'sdFc2':
  347. sdFc2 = new sdFc_2(model);
  348. await sdFc2.mountedThree();
  349. break;
  350. case 'sdFc5':
  351. sdFc5 = new sdFc_5(model);
  352. await sdFc5.mountedThree();
  353. break;
  354. case 'singleXkWindow':
  355. singleWindowXkObj = new singleWindowXk(model);
  356. await singleWindowXkObj.mountedThree();
  357. break;
  358. }
  359. }
  360. model.animate();
  361. resolve(null);
  362. });
  363. };
  364. export const destroy = () => {
  365. if (model) {
  366. model.isRender = false;
  367. console.log('场景销毁前信息----------->', model.renderer?.info);
  368. model.isRender = false;
  369. if (ddFc5) ddFc5.destroy();
  370. if (ddFc1) ddFc1.destroy();
  371. if (ddFc2) ddFc2.destroy();
  372. if (ddFc4) ddFc4.destroy();
  373. if (sdFc1) sdFc1.destroy();
  374. if (sdFc3) sdFc3.destroy();
  375. if (sdFc4) sdFc4.destroy();
  376. if (sdFc2) sdFc2.destroy();
  377. if (sdFc5) sdFc5.destroy();
  378. singleWindowXkObj.destroy();
  379. model.destroy();
  380. model = null;
  381. group = null;
  382. singleWindowXkObj = null;
  383. ddFc5 = null;
  384. ddFc1 = null;
  385. ddFc2 = null;
  386. ddFc4 = null;
  387. sdFc1 = null;
  388. sdFc3 = null;
  389. sdFc4 = null;
  390. sdFc2 = null;
  391. sdFc5 = null;
  392. }
  393. };