Scene copy.js 7.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274
  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. this.player.floorplanControls.enableZoom = true;
  129. } else {
  130. this.player.floorplanControls.enablePan = false;
  131. this.player.floorplanControls.enableZoom = false;
  132. }
  133. }
  134. setMode(mode) {
  135. this.player.setMode(mode);
  136. }
  137. onResize = (width, height) => {
  138. this.width = width !== undefined ? width : this.domElement.clientWidth;
  139. this.height = height !== undefined ? height : this.domElement.clientHeight;
  140. console.log("resize", this.width, this.height);
  141. (this.orthCamera.left = -this.width / 2),
  142. (this.orthCamera.right = this.width / 2),
  143. (this.orthCamera.bottom = -this.height / 2),
  144. (this.orthCamera.top = this.height / 2),
  145. this.orthCamera.updateProjectionMatrix();
  146. this.renderer.setSize(this.width, this.height);
  147. };
  148. render = () => {
  149. if (this.player) {
  150. this.player.update();
  151. this.renderer.render(this.scene, this.orthCamera);
  152. }
  153. };
  154. animate = () => {
  155. stats.begin();
  156. this.render();
  157. stats.end();
  158. requestAnimationFrame(this.animate);
  159. };
  160. resetCameraView() {
  161. this.orthCamera.zoom = this.defaultZoom;
  162. // this.orthCamera.position.set(0, 0, 0);
  163. // this.orthCamera.rotation.set(0, 10, 0);
  164. // this.orthCamera.updateMatrixWorld();
  165. }
  166. editing(item) {
  167. this.player.editing(item);
  168. }
  169. endScreenshot() {
  170. this.lockView(false);
  171. this.blobScreens = [];
  172. this.player.floorplanControls.reset();
  173. this.onResize();
  174. this.renderer.setSize(this.width, this.height);
  175. }
  176. screenshot(x, zoom) {
  177. var imgData, imgNode;
  178. const times = 4;
  179. this.orthCamera.zoom = zoom || this.defaultZoom;
  180. this.scene.position.x = x || 0;
  181. this.renderer.setSize(this.width * times, this.height * times);
  182. this.orthCamera.aspect = this.width / this.height;
  183. // this.player.floorplanControls.minZoom = 1;
  184. // this.orthCamera.zoom = 50;
  185. this.orthCamera.updateProjectionMatrix();
  186. this.renderer.render(this.scene, this.orthCamera, null, false);
  187. const dataURL = this.renderer.domElement.toDataURL("image/jpeg");
  188. this.blobScreens.push(dataURItoBlob(dataURL));
  189. // saveFile(dataURL, `${index}.jpg`);
  190. this.onResize(this.width, this.height);
  191. }
  192. exportScreenshot() {
  193. if (window.devicePixelRatio !== 1) {
  194. this.emit("devicePixelRatio");
  195. return;
  196. }
  197. this.player.floorplanControls.reset();
  198. this.lockView(true);
  199. this.setMode(0);
  200. // await sleep(500);
  201. this.orthCamera.zoom = this.defaultZoom;
  202. const object = this.boxManager.model;
  203. const total = object.children.length;
  204. if (total === 0) {
  205. return;
  206. console.error("没数据");
  207. }
  208. object.updateMatrixWorld();
  209. this.orthCamera.updateProjectionMatrix();
  210. const boundingBox = new THREE.Box3().setFromObject(object);
  211. // 计算宽度、高度和深度
  212. const width = boundingBox.max.x - boundingBox.min.x;
  213. const one = width / total;
  214. let slides = Math.floor(total / 3);
  215. // debugger;
  216. console.log("slides", slides);
  217. if (slides >= 1) {
  218. for (var i = 0; i <= slides; i++) {
  219. (function (index, that) {
  220. setTimeout(function () {
  221. const offset = -(one * 3 * index);
  222. console.log("Iteration:", offset);
  223. that.screenshot(offset);
  224. console.log(`Width: ${offset}`);
  225. if (index === slides) {
  226. console.log("last");
  227. that.scene.position.x = 0;
  228. that.emit("submitScreenshot");
  229. }
  230. }, index * 500);
  231. })(i, this); // 传递当前迭代的索引i给setTimeout的回调函数
  232. }
  233. } else {
  234. // 只有一个或0个
  235. if (total >= 1 && total <= 3) {
  236. console.log("total", total);
  237. this.player.floorplanControls.reset();
  238. this.screenshot(-0.3, 227);
  239. this.emit("submitScreenshot");
  240. }
  241. }
  242. }
  243. onBindEvent = () => {
  244. window.addEventListener("resize", this.onResize, false);
  245. };
  246. }