Scene.js 7.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269
  1. import * as THREE from "three";
  2. import Stats from "three/examples/jsm/libs/stats.module.js";
  3. import Player from "./player/Player.js";
  4. import BoxManager from "./box/BoxManager.js";
  5. import { Mitt } from "./mitt.js";
  6. import testData from "./save.json";
  7. import { dataURItoBlob, saveFile } from "./utils/utils.js";
  8. const stats = new Stats();
  9. function sleep(ms) {
  10. return new Promise((resolve) => setTimeout(resolve, ms));
  11. }
  12. export default class Scene extends Mitt {
  13. constructor(domElement) {
  14. super();
  15. this.domElement = domElement;
  16. this.scene = null;
  17. this.renderer = null;
  18. this.orthCamera = null;
  19. this.player = null;
  20. this.sceneType = 1;
  21. this.width = 0;
  22. this.height = 0;
  23. this.defaultZoom = 250;
  24. this.initCamPView = new THREE.Vector3();
  25. this.initCamRView = new THREE.Vector3();
  26. this.blobScreens = [];
  27. this.inited = false;
  28. this.init = () => {
  29. this.scene = new THREE.Scene();
  30. this.scene.background = new THREE.Color(0xf0f2f5);
  31. this.renderer = new THREE.WebGLRenderer({
  32. canvas: this.domElement,
  33. antialias: true,
  34. autoClear: true,
  35. preserveDrawingBuffer: true,
  36. });
  37. this.width = this.domElement.clientWidth;
  38. this.height = this.domElement.clientHeight;
  39. this.renderRes = window.devicePixelRatio;
  40. this.renderer.setSize(this.width, this.height);
  41. this.renderer.setPixelRatio(this.renderRes);
  42. console.log(this.width, this.height, this.renderRes);
  43. this.orthCamera = new THREE.OrthographicCamera(
  44. -this.width / 2,
  45. this.width / 2,
  46. this.height / 2,
  47. -this.height / 2,
  48. 0.1,
  49. 1000
  50. );
  51. this.orthCamera.zoom = this.defaultZoom;
  52. this.orthCamera.position.set(0, 10, 0);
  53. this.orthCamera.lookAt(0, 0, 0);
  54. // this.orthCamera.setViewOffset(this.width, this.height, 0, 0);
  55. this.orthCamera.updateProjectionMatrix();
  56. //player
  57. this.player = new Player(this);
  58. //stats
  59. domElement.parentNode.appendChild(stats.dom);
  60. stats.dom.style.pointerEvents = "none";
  61. stats.dom.style.left = "15%";
  62. stats.dom.style.display = "none";
  63. this.onBindEvent();
  64. this.inited = true;
  65. this.load();
  66. this.animate();
  67. };
  68. }
  69. load = (list, type, data) => {
  70. if (!list) return;
  71. // console.log("scene: ", list, type, data);
  72. //axesHeloer
  73. this.clearScene();
  74. this.sceneType = type;
  75. // const axesHelper = new THREE.AxesHelper(1);
  76. // this.scene.add(axesHelper);
  77. this.boxManager = new BoxManager(this);
  78. this.boxManager.load(list, type);
  79. //light
  80. this.loadLight();
  81. this.player.load(type, data || []);
  82. this.initCamPView.copy(this.orthCamera.position);
  83. this.initCamRView.copy(this.orthCamera.rotation);
  84. };
  85. clearScene() {
  86. for (var i = this.scene.children.length - 1; i >= 0; i--) {
  87. let obj = this.scene.children[i];
  88. this.scene.remove(obj);
  89. }
  90. }
  91. clearDrawScene() {
  92. for (var i = this.scene.children.length - 1; i >= 0; i--) {
  93. let obj = this.scene.children[i];
  94. if (
  95. String(obj.name).includes("marker_") ||
  96. String(obj.name).includes("line_") ||
  97. String(obj.name).includes("line_point_") ||
  98. String(obj.name).includes("circle_") ||
  99. String(obj.name).includes("pureText_")
  100. ) {
  101. this.scene.remove(obj);
  102. }
  103. }
  104. }
  105. deleteItemById(uuid, type) {
  106. for (var i = this.scene.children.length - 1; i >= 0; i--) {
  107. let obj = this.scene.children[i];
  108. if (obj.uuid === uuid) {
  109. console.log("deleteItemById-userData", obj.userData);
  110. this.player.deleteItemByType(type, obj.userData);
  111. this.scene.remove(obj);
  112. }
  113. }
  114. }
  115. deleteImageDataByIds(ids) {
  116. this.player.deleteImageDataByIds(ids);
  117. }
  118. loadLight = () => {
  119. const light = new THREE.AmbientLight(0xffffff, 1.5); // 柔和的白光
  120. this.scene.add(light);
  121. };
  122. setCamera = () => {};
  123. toHorizontal = () => {};
  124. toVertical = () => {};
  125. lockView(open) {
  126. if (open) {
  127. this.player.floorplanControls.enablePan = true;
  128. } else {
  129. this.player.floorplanControls.enablePan = false;
  130. }
  131. }
  132. setMode(mode) {
  133. this.player.setMode(mode);
  134. }
  135. onResize = (width, height) => {
  136. this.width = width !== undefined ? width : this.domElement.clientWidth;
  137. this.height = height !== undefined ? height : this.domElement.clientHeight;
  138. console.log("resize", this.width, this.height);
  139. (this.orthCamera.left = -this.width / 2),
  140. (this.orthCamera.right = this.width / 2),
  141. (this.orthCamera.bottom = -this.height / 2),
  142. (this.orthCamera.top = this.height / 2),
  143. this.orthCamera.updateProjectionMatrix();
  144. this.renderer.setSize(this.width, this.height);
  145. };
  146. render = () => {
  147. if (this.player) {
  148. this.player.update();
  149. this.renderer.render(this.scene, this.orthCamera);
  150. }
  151. };
  152. animate = () => {
  153. stats.begin();
  154. this.render();
  155. stats.end();
  156. requestAnimationFrame(this.animate);
  157. };
  158. resetCameraView() {
  159. this.orthCamera.zoom = this.defaultZoom;
  160. // this.orthCamera.position.set(0, 0, 0);
  161. // this.orthCamera.rotation.set(0, 10, 0);
  162. // this.orthCamera.updateMatrixWorld();
  163. }
  164. editing(item) {
  165. this.player.editing(item);
  166. }
  167. endScreenshot() {
  168. this.blobScreens = [];
  169. this.player.floorplanControls.reset();
  170. this.onResize();
  171. this.renderer.setSize(this.width, this.height);
  172. }
  173. screenshot(x, zoom) {
  174. var imgData, imgNode;
  175. const times = 4;
  176. this.orthCamera.zoom = zoom || this.defaultZoom;
  177. this.scene.position.x = x || 0;
  178. this.renderer.setSize(this.width * times, this.height * times);
  179. this.orthCamera.aspect = this.width / this.height;
  180. // this.player.floorplanControls.minZoom = 1;
  181. // this.orthCamera.zoom = 50;
  182. this.orthCamera.updateProjectionMatrix();
  183. this.renderer.render(this.scene, this.orthCamera, null, false);
  184. const dataURL = this.renderer.domElement.toDataURL("image/jpeg");
  185. this.blobScreens.push(dataURItoBlob(dataURL));
  186. // saveFile(dataURL, `${index}.jpg`);
  187. this.onResize(this.width, this.height);
  188. }
  189. test() {
  190. this.player.floorplanControls.reset();
  191. // await sleep(500);
  192. this.orthCamera.zoom = this.defaultZoom;
  193. const object = this.boxManager.model;
  194. let total;
  195. total = object.children.length;
  196. object.updateMatrixWorld();
  197. this.orthCamera.updateProjectionMatrix();
  198. const boundingBox = new THREE.Box3().setFromObject(object);
  199. // 计算宽度、高度和深度
  200. const width = boundingBox.max.x - boundingBox.min.x;
  201. const one = width / total;
  202. let slides = Math.floor(total / 3);
  203. console.log("slides", slides);
  204. if (slides > 1) {
  205. for (var i = 0; i <= slides; i++) {
  206. (function (index, that) {
  207. setTimeout(function () {
  208. const offset = -(one * 3 * index);
  209. console.log("Iteration:", offset);
  210. that.screenshot(offset);
  211. console.log(`Width: ${offset}`);
  212. if (index === slides) {
  213. console.log("last");
  214. that.scene.position.x = 0;
  215. that.emit("submitScreenshot");
  216. }
  217. }, index * 500);
  218. })(i, this); // 传递当前迭代的索引i给setTimeout的回调函数
  219. }
  220. } else {
  221. // 只有一个或0个
  222. if (total > 1 && total <= 3) {
  223. console.log("total", total);
  224. this.player.floorplanControls.reset();
  225. this.screenshot(-0.3, 227);
  226. this.emit("submitScreenshot");
  227. }
  228. }
  229. }
  230. test1() {
  231. const object = this.boxManager.model;
  232. for (var i = 0; i <= object.children.length; i++) {
  233. console.log(object.children[i]);
  234. this.scene.lookAt(this.boxManager.model);
  235. }
  236. }
  237. onBindEvent = () => {
  238. window.addEventListener("resize", this.onResize);
  239. };
  240. }