dantou.threejs.ts 5.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215
  1. import * as THREE from 'three';
  2. import { getTextCanvas, renderVideo } from '/@/utils/threejs/util';
  3. import gsap from 'gsap';
  4. // import * as dat from 'dat.gui';
  5. // const gui = new dat.GUI();
  6. // gui.domElement.style = 'position:absolute;top:100px;left:10px;z-index:99999999999999';
  7. class ddWindRect {
  8. model;
  9. modelName = 'ddcf';
  10. group: THREE.Object3D = new THREE.Object3D();
  11. animationTimer;
  12. isLRAnimation = true;
  13. direction = 1;
  14. constructor(model) {
  15. this.model = model;
  16. this.group.name = this.modelName;
  17. }
  18. addLight() {
  19. const directionalLight = new THREE.DirectionalLight(0xffffff, 1);
  20. directionalLight.position.set(42.4, 248, 86);
  21. this.group.add(directionalLight);
  22. directionalLight.target = this.group;
  23. // gui.add(directionalLight.position, 'x', -500, 500);
  24. // gui.add(directionalLight.position, 'y', -500, 500);
  25. // gui.add(directionalLight.position, 'z', -500, 500);
  26. const spotLight = new THREE.SpotLight();
  27. spotLight.angle = Math.PI / 16;
  28. spotLight.penumbra = 0;
  29. spotLight.castShadow = true;
  30. spotLight.distance = 0;
  31. spotLight.position.set(-470, -500, 500);
  32. this.group.add(spotLight);
  33. spotLight.shadow.camera.near = 0.5; // default
  34. spotLight.shadow.camera.far = 1000; // default
  35. spotLight.shadow.focus = 1;
  36. spotLight.shadow.bias = -0.000002;
  37. // gui.add(spotLight.position, 'x', -500, 500);
  38. // gui.add(spotLight.position, 'y', -500, 500);
  39. // gui.add(spotLight.position, 'z', -500, 500);
  40. // gui.add(spotLight, 'distance', 0, 1000);
  41. }
  42. // 设置模型位置
  43. setModalPosition() {
  44. this.group?.scale.set(22, 22, 22);
  45. this.group?.position.set(-10, 25, 20);
  46. }
  47. addFmText(selectData) {
  48. if (!this.group) {
  49. return;
  50. }
  51. const textArr = [
  52. {
  53. text: `单点式测风装置`,
  54. font: 'normal 32px Arial',
  55. color: '#009900',
  56. strokeStyle: '#002200',
  57. x: 140,
  58. y: 75,
  59. },
  60. {
  61. text: `风量(m3/min):`,
  62. font: 'normal 29px Arial',
  63. color: '#009900',
  64. strokeStyle: '#002200',
  65. x: 12,
  66. y: 133,
  67. },
  68. {
  69. text: `${selectData.m3 ? selectData.m3 : '-'}`,
  70. font: 'normal 29px Arial',
  71. color: '#009900',
  72. strokeStyle: '#002200',
  73. x: 311,
  74. y: 133,
  75. },
  76. {
  77. text: `风速(m/s): `,
  78. font: 'normal 29px Arial',
  79. color: '#009900',
  80. strokeStyle: '#002200',
  81. x: 12,
  82. y: 192,
  83. },
  84. {
  85. text: `${selectData.va ? selectData.va : '-'}`,
  86. font: 'normal 29px Arial',
  87. color: '#009900',
  88. strokeStyle: '#002200',
  89. x: 310,
  90. y: 192,
  91. },
  92. {
  93. text: `断面积(㎡):`,
  94. font: 'normal 29px Arial',
  95. color: '#009900',
  96. strokeStyle: '#002200',
  97. x: 12,
  98. y: 247,
  99. },
  100. {
  101. text: `${selectData.fsectarea ? selectData.fsectarea : '-'}`,
  102. font: 'normal 29px Arial',
  103. color: '#009900',
  104. strokeStyle: '#002200',
  105. x: 310,
  106. y: 247,
  107. },
  108. {
  109. text: `煤炭科学技术研究院有限公司研制`,
  110. font: 'normal 28px Arial',
  111. color: '#009900',
  112. strokeStyle: '#002200',
  113. x: 50,
  114. y: 302,
  115. },
  116. ];
  117. getTextCanvas(560, 346, textArr, '').then((canvas: HTMLCanvasElement) => {
  118. const textMap = new THREE.CanvasTexture(canvas); // 关键一步
  119. const textMaterial = new THREE.MeshBasicMaterial({
  120. map: textMap, // 设置纹理贴图
  121. transparent: true,
  122. side: THREE.DoubleSide, // 这里是双面渲染的意思
  123. });
  124. textMaterial.blending = THREE.CustomBlending;
  125. const monitorPlane = this.group?.getObjectByName('monitorText');
  126. if (monitorPlane) {
  127. monitorPlane.material = textMaterial;
  128. } else {
  129. const planeGeometry = new THREE.PlaneGeometry(5.6, 3.46); // 平面3维几何体PlaneGeometry
  130. const planeMesh = new THREE.Mesh(planeGeometry, textMaterial);
  131. planeMesh.name = 'monitorText';
  132. planeMesh.scale.set(0.26, 0.26, 0.26);
  133. planeMesh.position.set(-2.52, 0.038, -0.42);
  134. this.group?.add(planeMesh);
  135. }
  136. });
  137. }
  138. /* 风门动画 */
  139. render() {
  140. if (!this.model) {
  141. return;
  142. }
  143. if (this.isLRAnimation && this.group) {
  144. // 左右摇摆动画
  145. if (Math.abs(this.group.rotation.y) >= 0.2) {
  146. this.direction = -this.direction;
  147. this.group.rotation.y += 0.00002 * 30 * this.direction;
  148. } else {
  149. this.group.rotation.y += 0.00002 * 30 * this.direction;
  150. }
  151. }
  152. }
  153. /* 点击风窗,风窗全屏 */
  154. mousedownModel(intersects: THREE.Intersection<THREE.Object3D<THREE.Event>>[]) {
  155. this.isLRAnimation = false;
  156. if (this.animationTimer) {
  157. clearTimeout(this.animationTimer);
  158. this.animationTimer = null;
  159. }
  160. // 判断是否点击到视频
  161. intersects.find((intersect) => {
  162. intersect;
  163. return false;
  164. });
  165. }
  166. mouseUpModel() {
  167. // 10s后开始摆动
  168. if (!this.animationTimer && !this.isLRAnimation) {
  169. this.animationTimer = setTimeout(() => {
  170. this.isLRAnimation = true;
  171. }, 10000);
  172. }
  173. }
  174. resetModel() {
  175. clearTimeout(this.animationTimer);
  176. this.isLRAnimation = false;
  177. }
  178. mountedThree() {
  179. return new Promise((resolve) => {
  180. this.model.setGLTFModel([this.modelName]).then((gltf) => {
  181. this.group.name = this.modelName;
  182. this.group = gltf[0];
  183. this.setModalPosition();
  184. this.addLight();
  185. });
  186. });
  187. }
  188. destroy() {
  189. if (this.group) {
  190. this.model.clearGroup(this.group);
  191. }
  192. this.model = null;
  193. this.group = null;
  194. }
  195. }
  196. export default ddWindRect;