window.threejs.ts 6.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198
  1. import * as THREE from 'three';
  2. import UseThree from '../../../../utils/threejs/useThree';
  3. import singleWindow from './dandaoFc.threejs';
  4. import doubleWindow from './shuangdaoFc.threejs';
  5. import { animateCamera } from '/@/utils/threejs/util';
  6. import { useAppStore } from '/@/store/modules/app';
  7. // 模型对象、 文字对象
  8. let model,
  9. singleWindowObj,
  10. doubleWindowObj,
  11. group,
  12. windowType = 'singleWindow';
  13. const appStore = useAppStore();
  14. // 打灯光
  15. const addLight = () => {
  16. const pointLight2 = new THREE.PointLight(0xffeeee, 1, 83);
  17. pointLight2.position.set(-101, 34, 16);
  18. pointLight2.shadow.bias = 0.05;
  19. model.scene.add(pointLight2);
  20. const pointLight3 = new THREE.PointLight(0xffffff, 1, 150);
  21. pointLight3.position.set(-61, 37, 13.9);
  22. pointLight3.shadow.bias = 0.05;
  23. model.scene.add(pointLight3);
  24. const pointLight4 = new THREE.PointLight(0xffeeee, 0.6, 300);
  25. pointLight4.position.set(-2, 26, 20);
  26. pointLight4.shadow.bias = 0.05;
  27. model.scene.add(pointLight4);
  28. const pointLight5 = new THREE.PointLight(0xffffff, 0.8, 120);
  29. pointLight5.position.set(-54, 30, 23.8);
  30. pointLight5.shadow.bias = 0.05;
  31. model.scene.add(pointLight5);
  32. const pointLight7 = new THREE.PointLight(0xffffff, 1, 1000);
  33. pointLight7.position.set(45, 51, -4.1);
  34. pointLight7.shadow.bias = 0.05;
  35. model.scene.add(pointLight7);
  36. const spotLight = new THREE.SpotLight();
  37. spotLight.angle = Math.PI / 16;
  38. spotLight.penumbra = 0;
  39. spotLight.castShadow = true;
  40. spotLight.intensity = 1;
  41. spotLight.position.set(-231, 463, 687);
  42. model.scene.add(spotLight);
  43. spotLight.shadow.camera.near = 0.5; // default
  44. spotLight.shadow.camera.far = 1000; // default
  45. spotLight.shadow.focus = 1.2;
  46. spotLight.shadow.bias = -0.000002;
  47. };
  48. // // 重置摄像头
  49. // const resetCamera = () => {
  50. // model.camera.position.set(30.328, 58.993, 148.315);
  51. // model.camera.rotation.set(-31.85, 30.07, 17.29);
  52. // model.orbitControls?.update();
  53. // model.camera.updateProjectionMatrix();
  54. // };
  55. // 初始化左右摇摆动画
  56. const startAnimation = () => {
  57. // 定义鼠标点击事件
  58. model.canvasContainer?.addEventListener('mousedown', mouseEvent.bind(null));
  59. model.canvasContainer?.addEventListener('pointerup', (event) => {
  60. event.stopPropagation();
  61. // 单道、 双道
  62. if (windowType === 'doubleWindow') {
  63. doubleWindowObj.mouseUpModel.call(doubleWindowObj);
  64. } else if (windowType === 'singleWindow') {
  65. singleWindowObj.mouseUpModel.call(singleWindowObj);
  66. }
  67. });
  68. };
  69. // 鼠标点击、松开事件
  70. const mouseEvent = (event) => {
  71. event.stopPropagation();
  72. const widthScale = appStore.getWidthScale;
  73. const heightScale = appStore.getHeightScale;
  74. // 将鼠标位置归一化为设备坐标。x 和 y 方向的取值范围是 (-1 to +1)
  75. model.mouse.x =
  76. ((-model.canvasContainer.getBoundingClientRect().left * widthScale + event.clientX) / (model.canvasContainer.clientWidth * widthScale)) * 2 - 1;
  77. model.mouse.y =
  78. -((-model.canvasContainer.getBoundingClientRect().top + event.clientY) / (model.canvasContainer.clientHeight * heightScale)) * 2 + 1;
  79. (model.rayCaster as THREE.Raycaster).setFromCamera(model.mouse, model.camera as THREE.Camera);
  80. if (group) {
  81. const intersects = model.rayCaster?.intersectObjects(group.children, false) as THREE.Intersection[];
  82. if (intersects.length > 0) {
  83. // 单道、 双道
  84. if (windowType === 'doubleWindow') {
  85. doubleWindowObj.mousedownModel.call(doubleWindowObj, intersects);
  86. } else if (windowType === 'singleWindow') {
  87. singleWindowObj.mousedownModel.call(singleWindowObj, intersects);
  88. }
  89. }
  90. }
  91. };
  92. export const addFmText = (selectData) => {
  93. if (windowType === 'doubleWindow') {
  94. return doubleWindowObj.addFmText.call(doubleWindowObj, selectData);
  95. } else {
  96. return singleWindowObj.addFmText.call(singleWindowObj, selectData);
  97. }
  98. };
  99. export const play = (rotationParam, flag) => {
  100. if (windowType === 'doubleWindow') {
  101. return doubleWindowObj.play.call(doubleWindowObj, rotationParam, flag);
  102. } else {
  103. return singleWindowObj.play.call(singleWindowObj, rotationParam, flag);
  104. }
  105. };
  106. // 切换风窗类型
  107. export const setModelType = (type) => {
  108. windowType = type;
  109. return new Promise((resolve) => {
  110. // 显示双道风窗
  111. if (windowType === 'doubleWindow') {
  112. model.startAnimation = doubleWindowObj.render.bind(doubleWindowObj);
  113. group = doubleWindowObj.group;
  114. if (model.scene.getObjectByName('ddFc')) {
  115. model.scene.remove(singleWindowObj.group);
  116. }
  117. const oldCameraPosition = { x: 100, y: 0, z: 500 };
  118. model.scene.add(doubleWindowObj.group);
  119. setTimeout(async () => {
  120. resolve(null);
  121. const position = doubleWindowObj.group;
  122. await animateCamera(
  123. oldCameraPosition,
  124. oldCameraPosition,
  125. { x: 66.257, y: 57.539, z: 94.313 },
  126. { x: position.x, y: position.y, z: position.z },
  127. model
  128. );
  129. }, 300);
  130. } else if (windowType === 'singleWindow') {
  131. // 显示单道风窗
  132. model.startAnimation = singleWindowObj.render.bind(singleWindowObj);
  133. group = singleWindowObj.group;
  134. if (model.scene.getObjectByName('sdFc')) {
  135. model.scene.remove(doubleWindowObj.group);
  136. }
  137. const oldCameraPosition = { x: 100, y: 0, z: 500 };
  138. model.scene.add(singleWindowObj.group);
  139. setTimeout(async () => {
  140. resolve(null);
  141. const position = { x: 0, y: 0, z: 0 };
  142. await animateCamera(
  143. oldCameraPosition,
  144. { x: 0, y: 0, z: 0 },
  145. { x: 66.257, y: 57.539, z: 94.313 },
  146. { x: position.x, y: position.y, z: position.z },
  147. model
  148. );
  149. }, 300);
  150. }
  151. });
  152. };
  153. export const mountedThree = (playerVal1, playerVal2) => {
  154. return new Promise(async (resolve) => {
  155. model = new UseThree('#window3D');
  156. model.setEnvMap('test1');
  157. model.renderer.toneMappingExposure = 0.8;
  158. model.camera.position.set(100, 0, 1000);
  159. // 单道、 双道
  160. doubleWindowObj = new doubleWindow(model, playerVal1, playerVal2);
  161. singleWindowObj = new singleWindow(model, playerVal1);
  162. await doubleWindowObj.mountedThree();
  163. await singleWindowObj.mountedThree();
  164. model.animate();
  165. resolve(null);
  166. addLight();
  167. startAnimation();
  168. });
  169. };
  170. export const destroy = () => {
  171. if (model) {
  172. doubleWindowObj.destroy();
  173. singleWindowObj.destroy();
  174. model.deleteModal();
  175. model = null;
  176. group = null;
  177. singleWindowObj = null;
  178. doubleWindowObj = null;
  179. }
  180. };