balancePress.threejs.base.ts 10.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329
  1. import * as THREE from 'three';
  2. import { setModalCenter, getTextCanvas, renderVideo } from '/@/utils/threejs/util';
  3. import Smoke from '/@/views/vent/comment/threejs/Smoke';
  4. import gsap from 'gsap';
  5. // import * as dat from 'dat.gui';
  6. // const gui = new dat.GUI();
  7. // gui.domElement.style = 'position:absolute;top:100px;left:10px;z-index:99999999999999';
  8. class balancePressBase {
  9. model;
  10. modelName = 'balancePress';
  11. group: THREE.Object3D | null = null;
  12. topSmoke: Smoke | null = null;
  13. downSmoke: Smoke | null = null;
  14. outSmoke: Smoke | null = null;
  15. constructor(model) {
  16. this.model = model;
  17. }
  18. addLight() {
  19. const directionalLight = new THREE.DirectionalLight(0xffffff, 1);
  20. directionalLight.position.set(34, 7, -61);
  21. this.group?.add(directionalLight);
  22. directionalLight.target = this.group as THREE.Object3D;
  23. // gui.add(directionalLight.position, 'x', -200, 200);
  24. // gui.add(directionalLight.position, 'y', -200, 200);
  25. // gui.add(directionalLight.position, 'z', -200, 200);
  26. const pointLight5 = new THREE.PointLight(0xffffff, 0.8, 120);
  27. pointLight5.position.set(75, -44, 75);
  28. pointLight5.shadow.bias = 0.05;
  29. this.group?.add(pointLight5);
  30. const pointLight7 = new THREE.PointLight(0xffffff, 1, 1000);
  31. pointLight7.position.set(-7, 100, 8.5);
  32. pointLight7.shadow.bias = 0.05;
  33. this.group?.add(pointLight7);
  34. // gui.add(directionalLight.position, 'x', -100, 100);
  35. // gui.add(directionalLight.position, 'y', -100, 100);
  36. // gui.add(directionalLight.position, 'z', -100, 100);
  37. // gui.add(pointLight5.position, 'x', -500, 500);
  38. // gui.add(pointLight5.position, 'y', -500, 500);
  39. // gui.add(pointLight5.position, 'z', -500, 500);
  40. }
  41. /* 添加监控数据 */
  42. addText(selectData) {
  43. if (!this.group) {
  44. return;
  45. }
  46. const textArr = [
  47. {
  48. text: `煤矿巷道远程局部风机系统`,
  49. font: 'normal 30px Arial',
  50. color: '#009900',
  51. strokeStyle: '#002200',
  52. x: 50,
  53. y: 105,
  54. },
  55. {
  56. text: `进风量(m³/min):`,
  57. font: 'normal 30px Arial',
  58. color: '#009900',
  59. strokeStyle: '#002200',
  60. x: 0,
  61. y: 160,
  62. },
  63. {
  64. text: `${selectData.frontRearDP}`,
  65. font: 'normal 30px Arial',
  66. color: '#009900',
  67. strokeStyle: '#002200',
  68. x: 290,
  69. y: 160,
  70. },
  71. {
  72. text: `供风量(m³/min): `,
  73. font: 'normal 30px Arial',
  74. color: '#009900',
  75. strokeStyle: '#002200',
  76. x: 0,
  77. y: 217,
  78. },
  79. {
  80. text: ` ${selectData.sourcePressure}`,
  81. font: 'normal 30px Arial',
  82. color: '#009900',
  83. strokeStyle: '#002200',
  84. x: 280,
  85. y: 217,
  86. },
  87. {
  88. text: `故障诊断:`,
  89. font: 'normal 30px Arial',
  90. color: '#009900',
  91. strokeStyle: '#002200',
  92. x: 0,
  93. y: 275,
  94. },
  95. {
  96. text: `${selectData.warnLevel_str ? selectData.warnLevel_str : '-'}`,
  97. font: 'normal 30px Arial',
  98. color: '#009900',
  99. strokeStyle: '#002200',
  100. x: 280,
  101. y: 275,
  102. },
  103. {
  104. text: `煤炭科学技术研究院有限公司研制`,
  105. font: 'normal 28px Arial',
  106. color: '#009900',
  107. strokeStyle: '#002200',
  108. x: 20,
  109. y: 325,
  110. },
  111. ];
  112. getTextCanvas(526, 346, textArr, '').then((canvas: HTMLCanvasElement) => {
  113. const textMap = new THREE.CanvasTexture(canvas); // 关键一步
  114. const textMaterial = new THREE.MeshBasicMaterial({
  115. // 关于材质并未讲解 实操即可熟悉 这里是漫反射类似纸张的材质,对应的就有高光类似金属的材质.
  116. map: textMap, // 设置纹理贴图
  117. transparent: true,
  118. side: THREE.FrontSide, // 这里是双面渲染的意思
  119. });
  120. textMaterial.blending = THREE.CustomBlending;
  121. const monitorPlane = this.group?.getObjectByName('monitorText') as THREE.Mesh;
  122. if (monitorPlane) {
  123. monitorPlane.material = textMaterial;
  124. } else {
  125. const planeGeometry = new THREE.PlaneGeometry(526, 346); // 平面3维几何体PlaneGeometry
  126. const planeMesh = new THREE.Mesh(planeGeometry, textMaterial);
  127. planeMesh.name = 'monitorText';
  128. planeMesh.scale.set(0.0135, 0.0135, 0.0135);
  129. planeMesh.position.set(57.66, 0.81, 18.19);
  130. this.group?.add(planeMesh);
  131. }
  132. });
  133. }
  134. addVideo() {
  135. const videoPlayer1 = document.getElementById('jb-player1')?.getElementsByClassName('vjs-tech')[0];
  136. if (videoPlayer1) {
  137. const mesh = renderVideo(this.group, videoPlayer1, 'player1');
  138. if (mesh) {
  139. mesh.scale.set(0.222, 0.19, 0.2);
  140. mesh.position.set(-84.87, 0.298, 24.76);
  141. mesh.rotation.y = -Math.PI / 2;
  142. this.group?.add(mesh);
  143. }
  144. } else {
  145. const textArr = [
  146. {
  147. text: `无信号输入`,
  148. font: 'normal 40px Arial',
  149. color: '#009900',
  150. strokeStyle: '#002200',
  151. x: 170,
  152. y: 40,
  153. },
  154. ];
  155. getTextCanvas(560, 346, textArr, '').then((canvas: HTMLCanvasElement) => {
  156. const textMap = new THREE.CanvasTexture(canvas); // 关键一步
  157. const textMaterial = new THREE.MeshBasicMaterial({
  158. map: textMap, // 设置纹理贴图
  159. transparent: true,
  160. side: THREE.DoubleSide, // 这里是双面渲染的意思
  161. });
  162. textMaterial.blending = THREE.CustomBlending;
  163. const monitorPlane = this.group?.getObjectByName('noPlayer');
  164. if (monitorPlane) {
  165. monitorPlane.material = textMaterial;
  166. } else {
  167. const planeGeometry = new THREE.PlaneGeometry(100, 100); // 平面3维几何体PlaneGeometry
  168. const planeMesh = new THREE.Mesh(planeGeometry, textMaterial);
  169. if (!videoPlayer1) {
  170. planeMesh.name = 'noPlayer';
  171. planeMesh.scale.set(0.1, 0.075, 0);
  172. planeMesh.position.set(65.78, -2.68, 18.06);
  173. this.group?.add(planeMesh.clone());
  174. }
  175. }
  176. });
  177. }
  178. }
  179. playSmoke = (controlType, deviceType, frequency, state, duration?) => {
  180. if (frequency) {
  181. this.setSmokeFrequency(deviceType, frequency);
  182. }
  183. if (controlType === 'startSmoke') {
  184. this.runFly(deviceType, state, duration);
  185. }
  186. };
  187. async initFly() {
  188. // const fanObj = this.group?.getObjectByName('Equalization');
  189. const mesh = new THREE.Mesh();
  190. mesh.matrix = new THREE.Matrix4();
  191. mesh.position.set(35.251, 0.852, -35.243);
  192. mesh.scale.set(0.001, 0.001, 0.001);
  193. mesh.updateMatrix();
  194. if (!this.group) return;
  195. const topCurve = [
  196. {
  197. path0: new THREE.Vector3(14485.279, 1370.746, 56053.556).applyMatrix4(mesh.matrix),
  198. path1: new THREE.Vector3(7555.8, 1370.746, 54190.156).applyMatrix4(mesh.matrix),
  199. isSpread: true,
  200. spreadDirection: -1, //
  201. },
  202. ];
  203. const downCurve = [
  204. {
  205. path0: new THREE.Vector3(14485.279, -1370.746, 56053.556).applyMatrix4(mesh.matrix),
  206. path1: new THREE.Vector3(7555.82, -1370.746, 54190.156).applyMatrix4(mesh.matrix),
  207. isSpread: true,
  208. spreadDirection: -1, //
  209. },
  210. ];
  211. const outCurve = [
  212. {
  213. path0: new THREE.Vector3(-7555.818, -23.02, 11190.152).applyMatrix4(mesh.matrix),
  214. path1: new THREE.Vector3(-7555.818, -23.02, 165.96).applyMatrix4(mesh.matrix),
  215. isSpread: true,
  216. spreadDirection: 1, // 1是由小变大,-1是由大变小
  217. },
  218. ];
  219. if (!this.topSmoke) {
  220. this.topSmoke = new Smoke('/model/img/texture-smoke.png', '#ffffff', 0, 0.8, 0.05, 20);
  221. this.topSmoke.setPath(topCurve);
  222. await this.topSmoke.setPoints();
  223. this.group.add(this.topSmoke.points);
  224. }
  225. if (!this.downSmoke) {
  226. this.downSmoke = new Smoke('/model/img/texture-smoke.png', '#ffffff', 0, 0.8, 0.05, 20);
  227. this.downSmoke.setPath(downCurve);
  228. await this.downSmoke.setPoints();
  229. this.group.add(this.downSmoke.points);
  230. }
  231. if (!this.outSmoke) {
  232. this.outSmoke = new Smoke('/model/img/texture-smoke.png', '#ffffff', 0, 0.8, 0.05, 20);
  233. this.outSmoke.setPath(outCurve);
  234. await this.outSmoke.setPoints();
  235. this.group.add(this.outSmoke.points);
  236. }
  237. }
  238. runFly(deviceType, state, duration?) {
  239. if (state === 'open') {
  240. if (deviceType === 'top') {
  241. if (this.downSmoke?.frameId) {
  242. this.downSmoke.stopSmoke();
  243. }
  244. this.topSmoke?.startSmoke(duration);
  245. } else {
  246. if (this.topSmoke?.frameId) {
  247. this.topSmoke.stopSmoke();
  248. }
  249. this.downSmoke?.startSmoke(duration);
  250. }
  251. this.outSmoke?.startSmoke(duration);
  252. } else {
  253. if (this.downSmoke?.frameId) {
  254. this.downSmoke?.stopSmoke();
  255. }
  256. if (this.topSmoke?.frameId) {
  257. this.topSmoke?.stopSmoke();
  258. }
  259. if (this.outSmoke?.frameId) {
  260. this.outSmoke?.stopSmoke();
  261. }
  262. }
  263. }
  264. setSmokeFrequency = (deviceType, frequency) => {
  265. if (!this.topSmoke) return;
  266. const life = (frequency - 30) * 25;
  267. const duration = (Math.abs(life - this.topSmoke.life) / 500) * 25;
  268. let smoke;
  269. if (deviceType === 'top') {
  270. smoke = this.topSmoke;
  271. } else {
  272. smoke = this.downSmoke;
  273. }
  274. gsap.to(smoke, {
  275. life: life,
  276. duration: duration,
  277. ease: 'easeInCubic',
  278. overwrite: true,
  279. });
  280. };
  281. clearFly = () => {
  282. if (this.topSmoke) this.topSmoke.clearSmoke();
  283. if (this.downSmoke) this.downSmoke.clearSmoke();
  284. if (this.outSmoke) this.outSmoke.clearSmoke();
  285. };
  286. mountedThree() {
  287. return new Promise((resolve) => {
  288. this.model.setGLTFModel([this.modelName]).then(async (gltf) => {
  289. this.group = gltf[0];
  290. if (this.group) {
  291. this.group?.scale.set(0.1, 0.1, 0.1);
  292. await this.initFly();
  293. setModalCenter(this.group);
  294. resolve(null);
  295. this.addLight();
  296. }
  297. });
  298. });
  299. }
  300. destroy() {
  301. this.clearFly();
  302. this.model.clearGroup(this.group);
  303. this.model = null;
  304. this.group = null;
  305. }
  306. }
  307. export default balancePressBase;