|
@@ -0,0 +1,571 @@
|
|
|
+import * as THREE from 'three';
|
|
|
+// 导入轨道控制器
|
|
|
+import { OrbitControls } from 'three/examples/jsm/controls/OrbitControls.js';
|
|
|
+import { CSS3DRenderer } from 'three/examples/jsm/renderers/CSS3DRenderer.js';
|
|
|
+import { CSS2DRenderer } from 'three/examples/jsm/renderers/CSS2DRenderer.js';
|
|
|
+import { GLTFLoader } from 'three/examples/jsm/loaders/GLTFLoader.js';
|
|
|
+// import { FBXLoader } from 'three/examples/jsm/loaders/FBXLoader.js';
|
|
|
+import { DRACOLoader } from 'three/examples/jsm/loaders/DRACOLoader.js';
|
|
|
+import { EffectComposer } from 'three/examples/jsm/postprocessing/EffectComposer.js';
|
|
|
+import { FXAAShader } from 'three/examples/jsm/shaders/FXAAShader.js';
|
|
|
+import { ShaderPass } from 'three/examples/jsm/postprocessing/ShaderPass.js';
|
|
|
+import Stats from 'three/examples/jsm/libs/stats.module.js';
|
|
|
+import { useModelStore } from '/@/store/modules/threejs';
|
|
|
+import TWEEN from 'three/examples/jsm/libs/tween.module.js';
|
|
|
+import { RGBELoader } from 'three/examples/jsm/loaders/RGBELoader.js';
|
|
|
+import { useGlobSetting } from '/@/hooks/setting';
|
|
|
+import { getList } from '@/views/vent/sys/resources/file.api';
|
|
|
+import { saveModel } from '/@/utils/threejs/util';
|
|
|
+
|
|
|
+const globSetting = useGlobSetting();
|
|
|
+const baseApiUrl = globSetting.domainUrl;
|
|
|
+
|
|
|
+export function useThree(containerID: string, css3dContainerID: string, css2dContainerID: string) {
|
|
|
+
|
|
|
+}
|
|
|
+
|
|
|
+class UseThree {
|
|
|
+
|
|
|
+ constructor(canvasSelector, css3Canvas?, css2Canvas?) {
|
|
|
+ this.canvasContainer = document.querySelector(canvasSelector);
|
|
|
+ //初始化
|
|
|
+ this.init(css3Canvas, css2Canvas);
|
|
|
+ // this.animate();
|
|
|
+ window.addEventListener('resize', this.resizeRenderer.bind(this));
|
|
|
+ // 添加滚动事件,鼠标滚动模型执行动画
|
|
|
+ // window.addEventListener('wheel', this.wheelRenderer.bind(this));
|
|
|
+
|
|
|
+ // this.canvasContainer?.appendChild(gui.domElement);
|
|
|
+ }
|
|
|
+ init(css3Canvas?, css2Canvas?) {
|
|
|
+ // 初始化场景
|
|
|
+ this.initScene();
|
|
|
+ // 初始化环境光
|
|
|
+ // this.initLight();
|
|
|
+ // 初始化相机
|
|
|
+ this.initCamera();
|
|
|
+ //初始化渲染器
|
|
|
+ this.initRenderer();
|
|
|
+ // 初始化控制器
|
|
|
+ this.initControles();
|
|
|
+ if (css3Canvas) {
|
|
|
+ this.initCSS3Renderer(css3Canvas);
|
|
|
+ }
|
|
|
+ if (css2Canvas) {
|
|
|
+ this.initCSS2Renderer(css2Canvas);
|
|
|
+ }
|
|
|
+ // this.setTestPlane();
|
|
|
+ this.rayCaster = new THREE.Raycaster();
|
|
|
+ // this.createStats();
|
|
|
+ // this.removeSawtooth();
|
|
|
+ }
|
|
|
+
|
|
|
+ createStats() {
|
|
|
+ this.stats = Stats();
|
|
|
+ this.stats?.setMode(0);
|
|
|
+ this.stats.domElement.style = 'position: absolute; top: 300px';
|
|
|
+ this.canvasContainer?.appendChild(this.stats.domElement);
|
|
|
+ }
|
|
|
+
|
|
|
+ initScene() {
|
|
|
+ this.scene = new THREE.Scene();
|
|
|
+ // const axesHelper = new THREE.AxesHelper(100);
|
|
|
+ // this.scene?.add(axesHelper);
|
|
|
+ // const size = 1000;
|
|
|
+ // const divisions = 10;
|
|
|
+ // const gridHelper = new THREE.GridHelper(size, divisions);
|
|
|
+ // this.scene?.add(gridHelper);
|
|
|
+ }
|
|
|
+
|
|
|
+ initLight() {
|
|
|
+ // const light = new THREE.AmbientLight(0xffffff, 1);
|
|
|
+ // light.position.set(0, 1000, 1000);
|
|
|
+ // (this.scene as THREE.Scene).add(light);
|
|
|
+ }
|
|
|
+
|
|
|
+ initCamera() {
|
|
|
+ // this.camera = new THREE.PerspectiveCamera(50, this.canvasContainer.clientWidth / this.canvasContainer.clientHeight, 0.0000001, 1000);
|
|
|
+ if (!window['$camera']) {
|
|
|
+ throw new Error('threejs摄像头初始化异常!');
|
|
|
+ } else {
|
|
|
+ this.camera = window['$camera'] as THREE.PerspectiveCamera;
|
|
|
+ this.camera.layers.enableAll();
|
|
|
+ if (this.canvasContainer) this.camera.aspect = this.canvasContainer.clientWidth / this.canvasContainer.clientHeight;
|
|
|
+ this.camera.near = 0.0000001;
|
|
|
+ this.camera.far = 1000;
|
|
|
+ }
|
|
|
+
|
|
|
+ //
|
|
|
+ // const helper = new THREE.CameraHelper(this.camera);
|
|
|
+ // this.scene?.add(helper);
|
|
|
+ // gui.add(this.camera.position, 'x', 0.00001, 10000);
|
|
|
+ // gui.add(this.camera.position, 'y', 0.00001, 10000);
|
|
|
+ // gui.add(this.camera.position, 'z', 0.00001, 10000);
|
|
|
+ // gui.add(this.camera, 'near', 0.01, 1).step(0.01);
|
|
|
+ // gui.add(this.camera, 'far', 10, 100000);
|
|
|
+ // gui.add(this.camera, 'fov', 0, 180);
|
|
|
+ }
|
|
|
+
|
|
|
+ initRenderer() {
|
|
|
+ if (!window['$renderer']) {
|
|
|
+ throw new Error('threejs渲染器初始化异常!');
|
|
|
+ } else {
|
|
|
+ this.renderer = window['$renderer'];
|
|
|
+ if (this.canvasContainer) {
|
|
|
+ this.renderer.toneMappingExposure = 1.0;
|
|
|
+ this.renderer.toneMapping = THREE.ACESFilmicToneMapping;
|
|
|
+ // const gl = this.renderer?.getContext('webgl');
|
|
|
+ // gl && gl.getExtension('WEBGL_lose_context')?.restoreContext();
|
|
|
+ // this.renderer?.forceContextRestore()
|
|
|
+ this.renderer?.setSize(this.canvasContainer.clientWidth, this.canvasContainer.clientHeight);
|
|
|
+ this.canvasContainer.appendChild(this.renderer.domElement);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ initCSS3Renderer(cssCanvas) {
|
|
|
+ this.CSSCanvasContainer = document.querySelector(cssCanvas);
|
|
|
+ if (this.CSSCanvasContainer) {
|
|
|
+ this.css3dRender = new CSS3DRenderer() as CSS3DRenderer;
|
|
|
+ this.css3dRender.setSize(this.canvasContainer.clientWidth, this.canvasContainer.clientHeight);
|
|
|
+ this.CSSCanvasContainer?.appendChild(this.css3dRender.domElement);
|
|
|
+ this.css3dRender.render(this.scene as THREE.Scene, this.camera as THREE.PerspectiveCamera);
|
|
|
+ // this.css3dRender.domElement.style.pointerEvents = 'none';
|
|
|
+ // this.orbitControls = new OrbitControls(this.camera as THREE.Camera, this.css3dRender?.domElement) as OrbitControls;
|
|
|
+ // this.orbitControls.update();
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ initCSS2Renderer(cssCanvas) {
|
|
|
+ this.CSSCanvasContainer = document.querySelector(cssCanvas);
|
|
|
+ if (this.CSSCanvasContainer) {
|
|
|
+ this.css2dRender = new CSS2DRenderer();
|
|
|
+ this.css2dRender.setSize(this.canvasContainer.clientWidth, this.canvasContainer.clientHeight);
|
|
|
+ this.CSSCanvasContainer?.appendChild(this.css2dRender.domElement);
|
|
|
+ this.css2dRender.render(this.scene as THREE.Scene, this.camera as THREE.PerspectiveCamera);
|
|
|
+
|
|
|
+ // this.orbitControls = new OrbitControls(this.camera as THREE.Camera, this.css2dRender?.domElement) as OrbitControls;
|
|
|
+ // this.orbitControls.update();
|
|
|
+ // this.css2dRender.domElement.style.pointerEvents = 'none';
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ initControles() {
|
|
|
+ if (!window['$orbitControls']) {
|
|
|
+ throw new Error('threejs控制器初始化异常!');
|
|
|
+ } else {
|
|
|
+ this.orbitControls = window['$orbitControls'];
|
|
|
+ this.orbitControls.panSpeed = 1;
|
|
|
+ this.orbitControls.rotateSpeed = 1;
|
|
|
+ this.orbitControls.maxPolarAngle = Math.PI;
|
|
|
+ this.orbitControls.minPolarAngle = 0;
|
|
|
+ }
|
|
|
+ // this.orbitControls = new OrbitControls(this.camera as THREE.Camera, this.renderer?.domElement) as OrbitControls;
|
|
|
+ // this.orbitControls.update();
|
|
|
+ // this.orbitControls.minDistance = 1;
|
|
|
+ // this.orbitControls.maxDistance = 100;
|
|
|
+ // this.orbitControls.maxDistance = true;
|
|
|
+ }
|
|
|
+
|
|
|
+ setGLTFModel(modalNames, group = null) {
|
|
|
+ window['startTime'] = new Date().getTime();
|
|
|
+ const modelStore = useModelStore();
|
|
|
+ return new Promise(async (resolve, reject) => {
|
|
|
+ try {
|
|
|
+ const gltfLoader = new GLTFLoader();
|
|
|
+ const dracoLoader = new DRACOLoader();
|
|
|
+ dracoLoader.setDecoderPath('/model/draco/gltf/');
|
|
|
+ dracoLoader.setDecoderConfig({ type: 'js' }); //使用兼容性强的draco_decoder.js解码器
|
|
|
+ dracoLoader.preload();
|
|
|
+ gltfLoader.setDRACOLoader(dracoLoader);
|
|
|
+
|
|
|
+ const db = window['CustomDB'];
|
|
|
+ const resolvePromise: Promise<any>[] = [];
|
|
|
+
|
|
|
+ const modalNameArr = Object.prototype.toString.call(modalNames) === '[object Array]' ? modalNames : [modalNames];
|
|
|
+ const len = modalNameArr.length;
|
|
|
+
|
|
|
+ for (let i = 0; i < len; i++) {
|
|
|
+ resolvePromise[i] = new Promise(async (childResolve, reject) => {
|
|
|
+ try {
|
|
|
+ // 解析模型
|
|
|
+ const modalNameStr = modalNameArr[i];
|
|
|
+ const data = modelStore.modelArr.get(modalNameStr) || null;
|
|
|
+ let modalValue;
|
|
|
+ if (!data) {
|
|
|
+ const modalArr = await db.modal.where('modalName').equals(modalNameStr).toArray();
|
|
|
+ if (modalArr.length > 0) {
|
|
|
+ modalValue = modalArr[0].modalVal;
|
|
|
+ }
|
|
|
+ } else {
|
|
|
+ modalValue = data.modalVal;
|
|
|
+ }
|
|
|
+ if (modalValue) {
|
|
|
+ gltfLoader.parse(
|
|
|
+ modalValue,
|
|
|
+ '/model/glft/',
|
|
|
+ (gltf) => {
|
|
|
+ debugger;
|
|
|
+ const object = gltf.scene;
|
|
|
+ // setModalCenter(object);
|
|
|
+ object.traverse((obj) => {
|
|
|
+ if (obj instanceof THREE.Mesh) {
|
|
|
+ obj.material.emissiveIntensity = 1;
|
|
|
+ obj.material.emissiveMap = obj.material.map;
|
|
|
+ obj.material.blending = THREE.CustomBlending;
|
|
|
+
|
|
|
+ if (obj.material.opacity < 1) {
|
|
|
+ obj.material.transparent = true;
|
|
|
+ }
|
|
|
+ if (obj.material.map) {
|
|
|
+ obj.material.map.colorSpace = THREE.SRGBColorSpace;
|
|
|
+ obj.material.map.flipY = false;
|
|
|
+ obj.material.map.anisotropy = 1;
|
|
|
+ }
|
|
|
+ if (obj.material.emissiveMap) {
|
|
|
+ obj.material.emissiveMap.colorSpace = THREE.SRGBColorSpace;
|
|
|
+ obj.material.emissiveMap.flipY = false;
|
|
|
+ }
|
|
|
+
|
|
|
+ if (obj.material.map || obj.material.emissiveMap) {
|
|
|
+ obj.material.needsUpdate = true;
|
|
|
+ }
|
|
|
+
|
|
|
+ // if (envMap) {
|
|
|
+ // obj.material.envMap = envMap;
|
|
|
+ // obj.material.envMapIntensity = 1;
|
|
|
+ // }
|
|
|
+ // obj.renderOrder = 1;
|
|
|
+ }
|
|
|
+ });
|
|
|
+ object.animations = gltf.animations;
|
|
|
+ object.name = modalNameStr;
|
|
|
+ group?.add(object);
|
|
|
+ childResolve(object);
|
|
|
+ },
|
|
|
+ (err) => {
|
|
|
+ console.log(err);
|
|
|
+ }
|
|
|
+ );
|
|
|
+ } else {
|
|
|
+ // 开启线程下载
|
|
|
+ console.log('需要开启线程下载模型资源。。。。。');
|
|
|
+ const result = (await getList({ fileName: modalNameStr })) || [];
|
|
|
+ const file = result['records'][0];
|
|
|
+ if (file && file.path) {
|
|
|
+ gltfLoader.load(`${baseApiUrl}/sys/common/static/${file.path}`, async (glft) => {
|
|
|
+ if (glft) {
|
|
|
+ const object = glft.scene;
|
|
|
+ object.name = modalNameStr;
|
|
|
+ if (glft.animations.length > 0) {
|
|
|
+ object.animations = glft.animations;
|
|
|
+ }
|
|
|
+ group?.add(object);
|
|
|
+ childResolve(object);
|
|
|
+ const modalArr = await db.modal.where('modalName').equals(modalNameStr).toArray();
|
|
|
+ if (modalArr.length < 1) {
|
|
|
+ saveModel(modalNameStr, file.path, file.version);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ });
|
|
|
+ } else {
|
|
|
+ childResolve(null);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ } catch (error) {
|
|
|
+ console.log(error);
|
|
|
+ reject();
|
|
|
+ }
|
|
|
+ });
|
|
|
+ }
|
|
|
+ Promise.all(resolvePromise).then((objects) => {
|
|
|
+ dracoLoader.dispose();
|
|
|
+ resolve(objects);
|
|
|
+ });
|
|
|
+ } catch (error) {
|
|
|
+ reject('加载模型出错');
|
|
|
+ }
|
|
|
+ });
|
|
|
+ }
|
|
|
+
|
|
|
+ // setFBXModel(modalNames, group = null) {
|
|
|
+ // window['startTime'] = new Date().getTime();
|
|
|
+ // const modelStore = useModelStore();
|
|
|
+ // return new Promise(async (resolve, reject) => {
|
|
|
+ // try {
|
|
|
+ // const fbxLoader = new FBXLoader();
|
|
|
+
|
|
|
+ // fbxLoader.setPath('/model/fbx/');
|
|
|
+
|
|
|
+ // const db = window['CustomDB'];
|
|
|
+ // const resolvePromise: Promise<any>[] = [];
|
|
|
+
|
|
|
+ // let modalNameArr = Object.prototype.toString.call(modalNames) === '[object Array]' ? modalNames : [modalNames];
|
|
|
+ // let len = modalNameArr.length;
|
|
|
+
|
|
|
+ // for (let i = 0; i < len; i++) {
|
|
|
+ // resolvePromise[i] = new Promise(async (childResolve, reject) => {
|
|
|
+ // try {
|
|
|
+ // // 解析模型
|
|
|
+ // let modalValue;
|
|
|
+ // const modalNameStr = modalNameArr[i];
|
|
|
+ // let data = modelStore.modelArr.get(modalNameStr) || null;
|
|
|
+ // if (!data) {
|
|
|
+ // const modalArr = await db.modal.where('modalName').equals(modalNameStr).toArray();
|
|
|
+ // if (modalArr.length > 0) modalValue = modalArr[0].modalVal;
|
|
|
+ // } else {
|
|
|
+ // modalValue = data.modalVal;
|
|
|
+ // }
|
|
|
+ // if (modalValue) {
|
|
|
+ // const object = fbxLoader.parse(modalValue, '/model/fbx/');
|
|
|
+ // // const object = fbx.scene;
|
|
|
+ // // setModalCenter(object);
|
|
|
+ // if (object) {
|
|
|
+ // object.traverse((obj) => {
|
|
|
+ // if (obj instanceof THREE.Mesh) {
|
|
|
+ // obj.material.emissiveIntensity = 1;
|
|
|
+ // obj.material.emissiveMap = obj.material.map;
|
|
|
+ // obj.material.blending = THREE.CustomBlending;
|
|
|
+ // if (obj.material.opacity < 1) {
|
|
|
+ // obj.material.transparent = true;
|
|
|
+ // }
|
|
|
+ // if (obj.material.map) {
|
|
|
+ // obj.material.map.encoding = THREE.sRGBEncoding;
|
|
|
+ // obj.material.map.flipY = false;
|
|
|
+ // obj.material.map.anisotropy = 1;
|
|
|
+ // }
|
|
|
+ // if (obj.material.emissiveMap) {
|
|
|
+ // obj.material.emissiveMap.encoding = THREE.sRGBEncoding;
|
|
|
+ // obj.material.emissiveMap.flipY = false;
|
|
|
+ // }
|
|
|
+
|
|
|
+ // if (obj.material.map || obj.material.emissiveMap) {
|
|
|
+ // obj.material.needsUpdate = true;
|
|
|
+ // }
|
|
|
+
|
|
|
+ // // if (envMap) {
|
|
|
+ // // obj.material.envMap = envMap;
|
|
|
+ // // obj.material.envMapIntensity = 1;
|
|
|
+ // // }
|
|
|
+ // // obj.renderOrder = 1;
|
|
|
+ // }
|
|
|
+ // });
|
|
|
+ // object.animations = object.animations;
|
|
|
+ // object.name = modalNameStr;
|
|
|
+ // group?.add(object);
|
|
|
+ // childResolve(object);
|
|
|
+ // }
|
|
|
+ // }
|
|
|
+ // } catch (error) {
|
|
|
+ // console.log(error);
|
|
|
+ // reject();
|
|
|
+ // }
|
|
|
+ // });
|
|
|
+ // }
|
|
|
+
|
|
|
+ // Promise.all(resolvePromise).then((objects) => {
|
|
|
+ // resolve(objects);
|
|
|
+ // });
|
|
|
+ // } catch (error) {
|
|
|
+ // reject('加载模型出错');
|
|
|
+ // }
|
|
|
+ // });
|
|
|
+ // }
|
|
|
+
|
|
|
+ setTestPlane() {
|
|
|
+ const plane = new THREE.Mesh(new THREE.PlaneGeometry(10, 10), new THREE.MeshPhongMaterial({ color: 0x999999, specular: 0x101010 }));
|
|
|
+ plane.rotation.x = -Math.PI / 2;
|
|
|
+ plane.position.y = 0.03;
|
|
|
+ plane.receiveShadow = true;
|
|
|
+ this.scene?.add(plane);
|
|
|
+ }
|
|
|
+
|
|
|
+ removeSawtooth() {
|
|
|
+ this.composer = new EffectComposer(this.renderer as THREE.WebGLRenderer);
|
|
|
+ const FXAAShaderPass = new ShaderPass(FXAAShader);
|
|
|
+ FXAAShaderPass.uniforms['resolution'].value.set(1 / this.canvasContainer.clientWidth, 1 / this.canvasContainer.clientHeight);
|
|
|
+ FXAAShaderPass.renderToScreen = true;
|
|
|
+ this.composer.addPass(FXAAShaderPass);
|
|
|
+ }
|
|
|
+
|
|
|
+ /* 场景环境背景 */
|
|
|
+ setEnvMap(hdr) {
|
|
|
+ if (!this.scene) return;
|
|
|
+ // (this.scene as THREE.Scene).environment
|
|
|
+ new RGBELoader().setPath('/model/hdr/').load(hdr + '.hdr', (texture) => {
|
|
|
+ texture.colorSpace = THREE.SRGBColorSpace;
|
|
|
+ texture.mapping = THREE.EquirectangularReflectionMapping;
|
|
|
+ if (this.scene) (this.scene as THREE.Scene).environment = texture;
|
|
|
+ texture.dispose();
|
|
|
+ });
|
|
|
+ }
|
|
|
+
|
|
|
+ render() {
|
|
|
+ this.startAnimation();
|
|
|
+ this.orbitControls?.update();
|
|
|
+ this.camera?.updateMatrixWorld();
|
|
|
+ // this.composer?.render();
|
|
|
+ this.css3dRender?.render(this.scene as THREE.Scene, this.camera as THREE.PerspectiveCamera);
|
|
|
+ this.css2dRender?.render(this.scene as THREE.Scene, this.camera as THREE.PerspectiveCamera);
|
|
|
+ this.renderer?.render(this.scene as THREE.Object3D, this.camera as THREE.Camera);
|
|
|
+ }
|
|
|
+
|
|
|
+ timeRender() {
|
|
|
+ //设置为可渲染状态
|
|
|
+ this.renderEnabled = true;
|
|
|
+ //清除上次的延迟器
|
|
|
+ if (this.timeOut) {
|
|
|
+ clearTimeout(this.timeOut);
|
|
|
+ }
|
|
|
+ this.timeOut = setTimeout(() => {
|
|
|
+ this.renderEnabled = false;
|
|
|
+ }, 3000);
|
|
|
+ }
|
|
|
+
|
|
|
+ /* 漫游 */
|
|
|
+ startMY() {}
|
|
|
+ /* 初始动画 */
|
|
|
+ startAnimation() {}
|
|
|
+
|
|
|
+ renderAnimationScene() {}
|
|
|
+
|
|
|
+ animate() {
|
|
|
+ if (this.isRender) {
|
|
|
+ this.animationId = requestAnimationFrame(this.animate.bind(this));
|
|
|
+ const T = this.clock?.getDelta() || 0;
|
|
|
+ this.timeS = this.timeS + T;
|
|
|
+ if (this.timeS > this.renderT) {
|
|
|
+ this.renderAnimationScene();
|
|
|
+
|
|
|
+ if (this.renderEnabled) {
|
|
|
+ this.render();
|
|
|
+ }
|
|
|
+ this.stats?.update();
|
|
|
+ this.timeS = 0;
|
|
|
+ }
|
|
|
+ // this.stats?.update();
|
|
|
+ // // TWEEN.update();
|
|
|
+ // // this.renderAnimationScene();
|
|
|
+ // if (this.renderEnabled) {
|
|
|
+ // this.render();
|
|
|
+ // }
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ resizeRenderer() {
|
|
|
+ // 更新相机比例
|
|
|
+ if (this.camera) {
|
|
|
+ (this.camera as THREE.PerspectiveCamera).aspect = this.canvasContainer.clientWidth / this.canvasContainer.clientHeight;
|
|
|
+ // 刷新相机矩阵
|
|
|
+ this.camera?.updateProjectionMatrix();
|
|
|
+ }
|
|
|
+ // 设置场景尺寸
|
|
|
+ this.renderer?.setSize(this.canvasContainer.clientWidth, this.canvasContainer.clientHeight);
|
|
|
+ this.css3dRender?.setSize(this.canvasContainer.clientWidth, this.canvasContainer.clientHeight);
|
|
|
+ this.css2dRender?.setSize(this.canvasContainer.clientWidth, this.canvasContainer.clientHeight);
|
|
|
+ }
|
|
|
+
|
|
|
+ wheelRenderer(e: WheelEvent) {
|
|
|
+ const timeScale = e.deltaY > 0 ? 1 : -1;
|
|
|
+ this.animationAction?.setEffectiveTimeScale(timeScale);
|
|
|
+ (this.animationAction as THREE.AnimationAction).paused = false;
|
|
|
+ this.animationAction?.play();
|
|
|
+ if (this.timeoutId) {
|
|
|
+ clearTimeout(this.timeoutId);
|
|
|
+ }
|
|
|
+ this.timeoutId = setTimeout(() => {
|
|
|
+ this.animationAction?.halt(0.5);
|
|
|
+ }, 500);
|
|
|
+ }
|
|
|
+
|
|
|
+ clearMesh(item) {
|
|
|
+ item.geometry?.dispose();
|
|
|
+ if (item.material) {
|
|
|
+ const material = item.material;
|
|
|
+
|
|
|
+ for (const key of Object.keys(material)) {
|
|
|
+ const value = material[key];
|
|
|
+ // if (value && typeof value === 'object' && 'minFilter' in value) {
|
|
|
+ // // this.textureMap.set(value.uuid, value);
|
|
|
+ // value.dispose();
|
|
|
+ // }
|
|
|
+ if (value && typeof value === 'object' && value['dispose'] && typeof value['dispose'] === 'function') {
|
|
|
+ value.dispose();
|
|
|
+ }
|
|
|
+ }
|
|
|
+ material.dispose();
|
|
|
+ }
|
|
|
+ if (item.texture) {
|
|
|
+ item.texture.dispose();
|
|
|
+ }
|
|
|
+ }
|
|
|
+ clearGroup(group) {
|
|
|
+ const removeObj = (obj) => {
|
|
|
+ if (obj && obj?.children && obj?.children.length > 0) {
|
|
|
+ for (let i = obj?.children.length - 1; i >= 0; i--) {
|
|
|
+ const item = obj?.children[i];
|
|
|
+ if (item && item.children && item.children.length > 0) {
|
|
|
+ removeObj(item);
|
|
|
+ item?.clear();
|
|
|
+ } else {
|
|
|
+ if (item) {
|
|
|
+ if (item.parent) item.parent.remove(item);
|
|
|
+ this.clearMesh(item);
|
|
|
+ item.clear();
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ };
|
|
|
+ removeObj(group);
|
|
|
+ }
|
|
|
+
|
|
|
+ clearScene() {
|
|
|
+ this.clearGroup(this.scene);
|
|
|
+ // console.log('场景纹理数量----------->', this.textureMap.size);
|
|
|
+ this.textureMap.forEach((texture) => {
|
|
|
+ texture?.dispose();
|
|
|
+ });
|
|
|
+ this.textureMap.clear();
|
|
|
+ }
|
|
|
+
|
|
|
+ destroy() {
|
|
|
+ TWEEN.getAll().forEach((item) => {
|
|
|
+ item.stop();
|
|
|
+ });
|
|
|
+ TWEEN.removeAll();
|
|
|
+ this.isRender = false;
|
|
|
+ cancelAnimationFrame(this.animationId);
|
|
|
+ this.clearScene();
|
|
|
+ window.removeEventListener('resize', this.resizeRenderer);
|
|
|
+ // this.orbitControls?.dispose();
|
|
|
+ // this.scene?.environment?.dispose();
|
|
|
+ this.scene?.clear();
|
|
|
+ this.renderer?.dispose();
|
|
|
+ this.renderer?.getRenderTarget()?.dispose();
|
|
|
+
|
|
|
+ if (this.renderer && this.canvasContainer) this.canvasContainer.innerHTML = '';
|
|
|
+ if (this.CSSCanvasContainer && this.css3dRender) this.CSSCanvasContainer.innerHTML = '';
|
|
|
+
|
|
|
+ // if (this.renderer) this.renderer.domElement = null;
|
|
|
+ this.renderer?.clear();
|
|
|
+
|
|
|
+ if (this.css3dRender) this.css3dRender.domElement = null;
|
|
|
+ if (this.css2dRender) this.css2dRender.domElement = null;
|
|
|
+
|
|
|
+ if (this.canvasContainer) this.canvasContainer.innerHTML = '';
|
|
|
+ if (this.CSSCanvasContainer) this.CSSCanvasContainer.innerHTML = '';
|
|
|
+
|
|
|
+ this.camera = null;
|
|
|
+ this.orbitControls = null;
|
|
|
+ this.renderer = null;
|
|
|
+ this.stats = null;
|
|
|
+ this.scene = null;
|
|
|
+ this.css3dRender = null;
|
|
|
+ this.css2dRender = null;
|
|
|
+ THREE.Cache.clear();
|
|
|
+ console.log('场景销毁后信息----------->', window['$renderer']?.info, this.scene);
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+export default UseThree;
|