import * as THREE from "three"; import Stats from "three/examples/jsm/libs/stats.module.js"; import Player from "./player/Player.js"; import BoxManager from "./box/BoxManager.js"; import { Mitt } from "./mitt.js"; import testData from "./save.json"; import { dataURItoBlob, saveFile } from "./utils/utils.js"; const stats = new Stats(); function sleep(ms) { return new Promise((resolve) => setTimeout(resolve, ms)); } export default class Scene extends Mitt { constructor(domElement) { super(); this.domElement = domElement; this.scene = null; this.renderer = null; this.orthCamera = null; this.player = null; this.sceneType = 1; this.width = 0; this.height = 0; this.defaultZoom = 250; this.initCamPView = new THREE.Vector3(); this.initCamRView = new THREE.Vector3(); this.blobScreens = []; this.inited = false; this.init = () => { this.scene = new THREE.Scene(); this.scene.background = new THREE.Color(0xf0f2f5); this.renderer = new THREE.WebGLRenderer({ canvas: this.domElement, antialias: true, autoClear: true, preserveDrawingBuffer: true, }); this.width = this.domElement.clientWidth; this.height = this.domElement.clientHeight; this.renderRes = window.devicePixelRatio; this.renderer.setSize(this.width, this.height); this.renderer.setPixelRatio(this.renderRes); console.log(this.width, this.height, this.renderRes); this.orthCamera = new THREE.OrthographicCamera( -this.width / 2, this.width / 2, this.height / 2, -this.height / 2, 0.1, 1000 ); this.orthCamera.zoom = this.defaultZoom; this.orthCamera.position.set(0, 10, 0); this.orthCamera.lookAt(0, 0, 0); // this.orthCamera.setViewOffset(this.width, this.height, 0, 0); this.orthCamera.updateProjectionMatrix(); //player this.player = new Player(this); //stats domElement.parentNode.appendChild(stats.dom); stats.dom.style.pointerEvents = "none"; stats.dom.style.left = "15%"; stats.dom.style.display = "none"; this.onBindEvent(); this.inited = true; this.load(); this.animate(); }; } load = (list, type, data) => { if (!list) return; // console.log("scene: ", list, type, data); //axesHeloer this.clearScene(); this.sceneType = type; // const axesHelper = new THREE.AxesHelper(1); // this.scene.add(axesHelper); this.boxManager = new BoxManager(this); this.boxManager.load(list, type); //light this.loadLight(); this.player.load(type, data || []); this.initCamPView.copy(this.orthCamera.position); this.initCamRView.copy(this.orthCamera.rotation); }; clearScene() { for (var i = this.scene.children.length - 1; i >= 0; i--) { let obj = this.scene.children[i]; this.scene.remove(obj); } } clearDrawScene() { for (var i = this.scene.children.length - 1; i >= 0; i--) { let obj = this.scene.children[i]; if ( String(obj.name).includes("marker_") || String(obj.name).includes("line_") || String(obj.name).includes("line_point_") || String(obj.name).includes("circle_") || String(obj.name).includes("pureText_") ) { this.scene.remove(obj); } } } deleteItemById(uuid, type) { for (var i = this.scene.children.length - 1; i >= 0; i--) { let obj = this.scene.children[i]; if (obj.uuid === uuid) { console.log("deleteItemById-userData", obj.userData); this.player.deleteItemByType(type, obj.userData); this.scene.remove(obj); } } } deleteImageDataByIds(ids) { this.player.deleteImageDataByIds(ids); } loadLight = () => { const light = new THREE.AmbientLight(0xffffff, 1.5); // 柔和的白光 this.scene.add(light); }; setCamera = () => {}; toHorizontal = () => {}; toVertical = () => {}; lockView(open) { if (open) { this.player.floorplanControls.enablePan = true; } else { this.player.floorplanControls.enablePan = false; } } setMode(mode) { this.player.setMode(mode); } onResize = (width, height) => { this.width = width !== undefined ? width : this.domElement.clientWidth; this.height = height !== undefined ? height : this.domElement.clientHeight; console.log("resize", this.width, this.height); (this.orthCamera.left = -this.width / 2), (this.orthCamera.right = this.width / 2), (this.orthCamera.bottom = -this.height / 2), (this.orthCamera.top = this.height / 2), this.orthCamera.updateProjectionMatrix(); this.renderer.setSize(this.width, this.height); }; render = () => { if (this.player) { this.player.update(); this.renderer.render(this.scene, this.orthCamera); } }; animate = () => { stats.begin(); this.render(); stats.end(); requestAnimationFrame(this.animate); }; resetCameraView() { this.orthCamera.zoom = this.defaultZoom; // this.orthCamera.position.set(0, 0, 0); // this.orthCamera.rotation.set(0, 10, 0); // this.orthCamera.updateMatrixWorld(); } editing(item) { this.player.editing(item); } endScreenshot() { this.blobScreens = []; this.player.floorplanControls.reset(); this.onResize(); this.renderer.setSize(this.width, this.height); } screenshot(x, zoom) { var imgData, imgNode; const times = 4; this.orthCamera.zoom = zoom || this.defaultZoom; this.scene.position.x = x || 0; this.renderer.setSize(this.width * times, this.height * times); this.orthCamera.aspect = this.width / this.height; // this.player.floorplanControls.minZoom = 1; // this.orthCamera.zoom = 50; this.orthCamera.updateProjectionMatrix(); this.renderer.render(this.scene, this.orthCamera, null, false); const dataURL = this.renderer.domElement.toDataURL("image/jpeg"); this.blobScreens.push(dataURItoBlob(dataURL)); // saveFile(dataURL, `${index}.jpg`); this.onResize(this.width, this.height); } test() { this.player.floorplanControls.reset(); // await sleep(500); this.orthCamera.zoom = this.defaultZoom; const object = this.boxManager.model; let total; total = object.children.length; object.updateMatrixWorld(); this.orthCamera.updateProjectionMatrix(); const boundingBox = new THREE.Box3().setFromObject(object); // 计算宽度、高度和深度 const width = boundingBox.max.x - boundingBox.min.x; const one = width / total; let slides = Math.floor(total / 3); console.log("slides", slides); if (slides > 1) { for (var i = 0; i <= slides; i++) { (function (index, that) { setTimeout(function () { const offset = -(one * 3 * index); console.log("Iteration:", offset); that.screenshot(offset); console.log(`Width: ${offset}`); if (index === slides) { console.log("last"); that.scene.position.x = 0; that.emit("submitScreenshot"); } }, index * 500); })(i, this); // 传递当前迭代的索引i给setTimeout的回调函数 } } else { // 只有一个或0个 if (total > 1 && total <= 3) { console.log("total", total); this.player.floorplanControls.reset(); this.screenshot(-0.3, 227); this.emit("submitScreenshot"); } } } test1() { const object = this.boxManager.model; for (var i = 0; i <= object.children.length; i++) { console.log(object.children[i]); this.scene.lookAt(this.boxManager.model); } } onBindEvent = () => { window.addEventListener("resize", this.onResize); }; }