| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306 |
- 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 * 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) {
- // setModalCenter(this.group);
- this.addLight();
- this.setModelPosition();
- this.initModules().then(resolve);
- }
- });
- });
- }
- destroy() {
- if (!this.model) return;
- this.elements.forEach((element) => {
- this.model.clearGroup(element);
- });
- }
- // 设置模型位置
- setModelPosition() {
- if (!this.group) return;
- this.group.scale.set(0.6, 0.6, 0.6);
- // const ff = gui.addFolder(`位置调整`);
- // ff.add(this.group.position, 'x', -100, 100);
- // ff.add(this.group.position, 'y', -100, 100);
- // ff.add(this.group.position, 'z', -100, 100);
- this.group.position.set(0, 0, -60);
- 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.oldOpacityFactor = 0.4;
- }
- if (g instanceof CSS3DObject) {
- g.element.style.setProperty('opacity', '0.5');
- }
- });
- }
- strongElements(eles: unknown[]) {
- eles.forEach((g) => {
- if (g instanceof Smoke) {
- g.oldOpacityFactor = 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 curveFan1Right = this.generateSmokePath(
- [
- new THREE.Vector3(-85.685, 4.208, 43.895),
- new THREE.Vector3(-85.685, 2.208, 41.895),
- new THREE.Vector3(-85.685, 2.188, 35.327),
- new THREE.Vector3(-85.685, 0.784, 33.086),
- new THREE.Vector3(-85.685, 0.784, 27.848),
- new THREE.Vector3(-85.685, 4.724, 21.565),
- new THREE.Vector3(-85.685, 4.724, -12.993),
- new THREE.Vector3(-26.191, 4.724, -13.232),
- new THREE.Vector3(-25.608, 4.724, -47.022),
- new THREE.Vector3(80.038, 4.724, -47.022),
- ],
- true
- );
- // 右侧风机-备风机进风
- const curveFan2Right = this.generateSmokePath(
- [
- new THREE.Vector3(-85.685, 1.475, 43.895),
- new THREE.Vector3(-85.685, -0.525, 41.895),
- new THREE.Vector3(-85.685, -0.525, 35.327),
- new THREE.Vector3(-85.685, 0.784, 33.086),
- new THREE.Vector3(-85.685, 0.784, 27.848),
- new THREE.Vector3(-85.685, 4.724, 21.565),
- new THREE.Vector3(-85.685, 4.724, -12.993),
- new THREE.Vector3(-26.191, 4.724, -13.232),
- new THREE.Vector3(-25.608, 4.724, -47.022),
- new THREE.Vector3(80.038, 4.724, -47.022),
- ],
- true
- );
- // 左侧风机-主风机进风
- const curveFan1Left = this.generateSmokePath(
- [
- new THREE.Vector3(-85.685, 4.188, 4.729),
- new THREE.Vector3(-85.685, 2.188, 2.729),
- new THREE.Vector3(-85.685, 2.188, -3.84),
- new THREE.Vector3(-85.685, 0.784, -6.081),
- new THREE.Vector3(-85.685, 0.784, -12.912),
- new THREE.Vector3(80.251, 0.784, -12.912),
- ],
- true
- );
- // 左侧风机-备风机进风
- const curveFan2Left = this.generateSmokePath(
- [
- new THREE.Vector3(-85.685, 1.475, 4.729),
- new THREE.Vector3(-85.685, -0.525, 2.729),
- new THREE.Vector3(-85.685, -0.508, -3.84),
- new THREE.Vector3(-85.685, 0.784, -6.081),
- new THREE.Vector3(-85.685, 0.784, -12.912),
- new THREE.Vector3(80.251, 0.784, -12.912),
- ],
- true
- );
- const group1 = new THREE.Group();
- const smokeFan1Right = new Smoke('/model/img/texture-smoke.png', '#ffffff', 0, 0.75, 0.5, 400);
- smokeFan1Right.setPath(curveFan1Right);
- this.elements.push(smokeFan1Right);
- const smokeFan2Right = new Smoke('/model/img/texture-smoke.png', '#ffffff', 0, 0.75, 0.5, 400);
- smokeFan2Right.setPath(curveFan2Right);
- this.elements.push(smokeFan2Right);
- const smokeFan1Left = new Smoke('/model/img/texture-smoke.png', '#ffffff', 0, 0.75, 0.5, 400);
- smokeFan1Left.setPath(curveFan1Left);
- this.elements.push(smokeFan1Left);
- const smokeFan2Left = new Smoke('/model/img/texture-smoke.png', '#ffffff', 0, 0.75, 0.5, 400);
- smokeFan2Left.setPath(curveFan2Left);
- this.elements.push(smokeFan2Left);
- await smokeFan1Right.setPoints();
- this.group?.add(smokeFan1Right.points);
- await smokeFan2Right.setPoints();
- this.group?.add(smokeFan2Right.points);
- await smokeFan1Left.setPoints();
- this.group?.add(smokeFan1Left.points);
- await smokeFan2Left.setPoints();
- this.group?.add(smokeFan2Left.points);
- // 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: 'fan1RightOpen',
- context: group1,
- behavior: () => {
- this.weakElements(this.elements);
- this.startAnimation([smokeFan1Right]);
- this.strongElements([smokeFan1Right]);
- },
- });
- this.modules.push({
- name: 'fan2RightOpen',
- context: group1,
- behavior: () => {
- this.weakElements(this.elements);
- this.startAnimation([smokeFan2Right]);
- this.strongElements([smokeFan2Right]);
- },
- });
- this.modules.push({
- name: 'fan1LeftOpen',
- context: group1,
- behavior: () => {
- this.weakElements(this.elements);
- this.startAnimation([smokeFan1Left]);
- this.strongElements([smokeFan1Left]);
- },
- });
- this.modules.push({
- name: 'fan2LeftOpen',
- context: group1,
- behavior: () => {
- this.weakElements(this.elements);
- this.startAnimation([smokeFan2Left]);
- this.strongElements([smokeFan2Left]);
- },
- });
- }
- /** 生成适用于 Smoke 的曲线数据,输入途径点,输出路径,如果是进风类型,首个线段将有扩散效果,出风则是末尾线段有扩散效果 */
- generateSmokePath(points: THREE.Vector3[], airIn?: boolean, airOut?: boolean) {
- const result: any[] = [];
- for (let index = 1; index < points.length; index++) {
- const path0 = points[index - 1];
- const path1 = points[index];
- const path = {
- path0,
- path1,
- isSpread: false,
- spreadDirection: 0,
- };
- if (airIn) {
- // 首个线段需要扩散,由大变小
- path.isSpread = index === 1;
- path.spreadDirection = -1;
- }
- if (airOut) {
- // 首个线段需要扩散,由小变大
- path.isSpread = index === points.length - 1;
- path.spreadDirection = 1;
- }
- result.push(path);
- }
- return result;
- }
- }
- export default ModelContext;
|