window.threejs.ts 6.2 KB

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