|
@@ -0,0 +1,274 @@
|
|
|
+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;
|
|
|
+ this.player.floorplanControls.enableZoom = true;
|
|
|
+ } else {
|
|
|
+ this.player.floorplanControls.enablePan = false;
|
|
|
+ this.player.floorplanControls.enableZoom = 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.lockView(false);
|
|
|
+ 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);
|
|
|
+ }
|
|
|
+
|
|
|
+ exportScreenshot() {
|
|
|
+ if (window.devicePixelRatio !== 1) {
|
|
|
+ this.emit("devicePixelRatio");
|
|
|
+ return;
|
|
|
+ }
|
|
|
+ this.player.floorplanControls.reset();
|
|
|
+ this.lockView(true);
|
|
|
+ this.setMode(0);
|
|
|
+ // await sleep(500);
|
|
|
+ this.orthCamera.zoom = this.defaultZoom;
|
|
|
+ const object = this.boxManager.model;
|
|
|
+ const total = object.children.length;
|
|
|
+ if (total === 0) {
|
|
|
+ return;
|
|
|
+ console.error("没数据");
|
|
|
+ }
|
|
|
+
|
|
|
+ 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);
|
|
|
+ // debugger;
|
|
|
+ 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");
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ onBindEvent = () => {
|
|
|
+ window.addEventListener("resize", this.onResize, false);
|
|
|
+ };
|
|
|
+}
|