import * as THREE from 'three'; import { setModalCenter } from '/@/utils/threejs/util'; import Smoke from '../../comment/threejs/Smoke'; import { CSS3DObject } from 'three/examples/jsm/renderers/CSS3DRenderer'; // import { setModalCenter } from '/@/utils/threejs/util'; // import * as dat from 'dat.gui'; // const gui = new dat.GUI(); // gui.domElement.style = 'position:absolute;top:100px;left:10px;z-index:99999999999999'; class ModelContext { model; // modelName = 'jbfj-hd'; modelName = 'jbfj-dual'; /** 本模型的根3D对象 */ group?: THREE.Object3D; /** 本模型所包含的所有元素合集 */ private elements: unknown[] = []; /** 本模型支持的 Object3DGroup 模块 */ private modules: { /** 模块名称 */ name: string; /** 控制该模块所用的上下文 */ context: THREE.Object3D; /** 控制时行为声明 */ behavior: (context: THREE.Object3D) => void; }[] = []; constructor(model) { this.model = model; } addLight() { // optional implementation } /** 设置模型类型并切换,不同的类型通常对应不同的具体模型,在模型总控制器下的具体模型会根据传入的参数彼此交互、切换 */ setModelType(modelType: string) { this.modules.forEach(({ name, context, behavior }) => { if (name === modelType) { behavior(context); } }); } /** 初始化css元素,将css元素选择器传入,该方法会将这些元素按顺序放入传入的锚点中 */ initCssElement() { // selectors.forEach((selector, index) => { // const element = document.querySelector(selector) as HTMLElement; // if (element) { // const css3D = new CSS3DSprite(element); // this.cssSprites.push(css3D); // css3D.name = selector; // css3D.scale.set(0.05, 0.05, 0.05); // // const ff = gui.addFolder(`css元素${index}`); // // ff.add(css3D.position, 'x', -100, 100); // // ff.add(css3D.position, 'y', -100, 100); // // ff.add(css3D.position, 'z', -100, 100); // if (index < anchors.length) { // const [x, y, z] = anchors[index]; // css3D.position.set(x, y, z); // this.group?.add(css3D); // } else { // console.warn(`指定的元素${selector}没有合适的位置放置`); // } // } // }); } mountedThree() { return new Promise((resolve) => { this.model.setGLTFModel([this.modelName]).then(async (gltf) => { this.group = gltf[0]; if (this.group) { this.addLight(); this.setModalPosition(); this.initModules(); setModalCenter(this.group); resolve(null); } }); }); } destroy() { if (!this.model) return; this.elements.forEach((element) => { this.model.clearGroup(element); }); } // 设置模型位置 setModalPosition() { if (!this.group) return; this.group.scale.set(0.7, 0.7, 0.7); this.group.position.set(0, 6, -50); this.group.rotation.y = Math.PI / 2; } // hideElements(eles: THREE.Object3D[]) { // eles.forEach((g) => { // g.visible = false; // }); // } // showElements(eles: THREE.Object3D[]) { // eles.forEach((g) => { // g.visible = true; // }); // } weakElements(eles: unknown[]) { eles.forEach((g) => { if (g instanceof Smoke) { g.opacityFactor = 0.4; } if (g instanceof CSS3DObject) { g.element.style.setProperty('opacity', '0.5'); } }); } strongElements(eles: unknown[]) { eles.forEach((g) => { if (g instanceof Smoke) { g.opacityFactor = 0.75; } if (g instanceof CSS3DObject) { g.element.style.setProperty('opacity', '1'); } }); } startAnimation(eles: unknown[]) { eles.forEach((g) => { if (g instanceof Smoke) { g.startSmoke(); } }); } stopAnimation(eles: unknown[]) { eles.forEach((g) => { if (g instanceof Smoke) { g.stopSmoke(); } }); } /** 核心方法,初始化本模型的各个模块,这些模块可以实现特定场景的展示、控制等功能 */ async initModules() { if (this.elements.length > 0) return; const curve1 = [ { path0: new THREE.Vector3(10, 0, -10), path1: new THREE.Vector3(20, 0, -10), isSpread: false, spreadDirection: 0, }, { path0: new THREE.Vector3(10, 0, -10), path1: new THREE.Vector3(10, 0, -20), isSpread: true, spreadDirection: 1, // 1是由小变大,-1是由大变小 }, ]; const group1 = new THREE.Group(); const smoke1 = new Smoke('/model/img/texture-smoke.png', '#ffffff', 0, 0.75, 0.5, 400); smoke1.setPath(curve1); await smoke1.setPoints(); this.elements.push(smoke1); const element = document.getElementById('inputBox') as HTMLElement; if (element) { const fanLocalCSS3D = new CSS3DObject(element); fanLocalCSS3D.name = 'text1'; fanLocalCSS3D.scale.set(0.04, 0.04, 0.04); fanLocalCSS3D.rotation.y = -Math.PI / 2; fanLocalCSS3D.position.set(-85.68, 5.97, -3.39); group1.add(fanLocalCSS3D); this.elements.push(fanLocalCSS3D); } this.modules.push({ name: 'state1', context: group1, behavior: () => { this.weakElements(this.elements); this.strongElements([smoke1]); }, }); } } export default ModelContext;