dantou.threejs.ts 5.2 KB

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