|
@@ -1,8 +1,8 @@
|
|
|
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';
|
|
|
+import { CSS3DObject, CSS3DSprite } 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';
|
|
|
|
|
@@ -14,6 +14,7 @@ class ModelContext {
|
|
|
group?: THREE.Object3D;
|
|
|
/** 本模型所包含的所有元素合集 */
|
|
|
private elements: unknown[] = [];
|
|
|
+ private cssSprites: CSS3DSprite[] = [];
|
|
|
/** 本模型支持的 Object3DGroup 模块 */
|
|
|
private modules: {
|
|
|
/** 模块名称 */
|
|
@@ -41,38 +42,16 @@ class ModelContext {
|
|
|
});
|
|
|
}
|
|
|
|
|
|
- /** 初始化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.group.scale.set(2, 2, 2);
|
|
|
// setModalCenter(this.group);
|
|
|
this.addLight();
|
|
|
this.setModelPosition();
|
|
|
+ this.initCssElement();
|
|
|
this.initModules().then(resolve);
|
|
|
}
|
|
|
});
|
|
@@ -139,85 +118,52 @@ class ModelContext {
|
|
|
});
|
|
|
}
|
|
|
stopAnimation(eles: unknown[]) {
|
|
|
- eles.forEach((g) => {
|
|
|
- if (g instanceof Smoke) {
|
|
|
- g.stopSmoke();
|
|
|
- }
|
|
|
+ const smokes = eles.filter((g) => {
|
|
|
+ return g instanceof Smoke;
|
|
|
});
|
|
|
+ return Promise.all(smokes.map((e) => e.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 curveFan1Right = this.generateSmokePath(['dian', 'dian1', 'dian2', 'dian3', 'dian4', 'dian5', 'dian6', 'dian7', 'dian8'], 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 curveFan2Right = this.generateSmokePath(['dian9', 'dian10', 'dian2', 'dian3', 'dian4', 'dian5', 'dian6', 'dian7', 'dian8'], 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 curveFan1Left = this.generateSmokePath(['dian11', 'dian12', 'dian15', 'dian16', 'dian17'], 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 curveFan2Left = this.generateSmokePath(['dian14', 'dian13', 'dian15', 'dian16', 'dian17'], true);
|
|
|
+ // 右侧巷道-回风前段
|
|
|
+ const curveTunnelRight = this.generateSmokePath(['dian18', 'dian19', 'dian20']);
|
|
|
+ // 左侧巷道-回风前段
|
|
|
+ const curveTunnelLeft = this.generateSmokePath(['dian20', 'dian22']);
|
|
|
+ // 左侧巷道-回风全长
|
|
|
+ const curveTunnelMajor = this.generateSmokePath(['dian21', 'dian22']);
|
|
|
+
|
|
|
const group1 = new THREE.Group();
|
|
|
- const smokeFan1Right = new Smoke('/model/img/texture-smoke.png', '#ffffff', 0, 0.75, 0.5, 400);
|
|
|
+ const smokeFan1Right = new Smoke('/model/img/texture-smoke.png', '#ffffff', 10, 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);
|
|
|
+ const smokeFan2Right = new Smoke('/model/img/texture-smoke.png', '#ffffff', 10, 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);
|
|
|
+ const smokeFan1Left = new Smoke('/model/img/texture-smoke.png', '#ffffff', 10, 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);
|
|
|
+ const smokeFan2Left = new Smoke('/model/img/texture-smoke.png', '#ffffff', 10, 0.75, 0.5, 400);
|
|
|
smokeFan2Left.setPath(curveFan2Left);
|
|
|
this.elements.push(smokeFan2Left);
|
|
|
+ const smokeTunnelRight = new Smoke('/model/img/texture-smoke.png', '#ffffff', 0, 0.35, 1.5, 200);
|
|
|
+ smokeTunnelRight.setPath(curveTunnelRight);
|
|
|
+ this.elements.push(smokeTunnelRight);
|
|
|
+ const smokeTunnelLeft = new Smoke('/model/img/texture-smoke.png', '#ffffff', 0, 0.35, 1.5, 200);
|
|
|
+ smokeTunnelLeft.setPath(curveTunnelLeft);
|
|
|
+ this.elements.push(smokeTunnelLeft);
|
|
|
+ const smokeTunnelMajor = new Smoke('/model/img/texture-smoke.png', '#ffffff', 0, 0.35, 1.5, 200);
|
|
|
+ smokeTunnelMajor.setPath(curveTunnelMajor);
|
|
|
+ this.elements.push(smokeTunnelMajor);
|
|
|
|
|
|
await smokeFan1Right.setPoints();
|
|
|
this.group?.add(smokeFan1Right.points);
|
|
@@ -227,58 +173,146 @@ class ModelContext {
|
|
|
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);
|
|
|
- // }
|
|
|
+ await smokeTunnelRight.setPoints();
|
|
|
+ this.group?.add(smokeTunnelRight.points);
|
|
|
+ await smokeTunnelLeft.setPoints();
|
|
|
+ this.group?.add(smokeTunnelLeft.points);
|
|
|
+ await smokeTunnelMajor.setPoints();
|
|
|
+ this.group?.add(smokeTunnelMajor.points);
|
|
|
|
|
|
+ // 双巷道的通风机都开启有4种情况
|
|
|
+ this.modules.push({
|
|
|
+ name: 'fan1RightOpen&fan1LeftOpen',
|
|
|
+ context: group1,
|
|
|
+ behavior: () => {
|
|
|
+ this.stopAnimation(this.elements).then(() => {
|
|
|
+ this.startAnimation([smokeFan1Right, smokeFan1Left, smokeTunnelRight, smokeTunnelMajor]);
|
|
|
+ });
|
|
|
+ },
|
|
|
+ });
|
|
|
+ this.modules.push({
|
|
|
+ name: 'fan2RightOpen&fan1LeftOpen',
|
|
|
+ context: group1,
|
|
|
+ behavior: () => {
|
|
|
+ this.stopAnimation(this.elements).then(() => {
|
|
|
+ this.startAnimation([smokeFan2Right, smokeFan1Left, smokeTunnelRight, smokeTunnelMajor]);
|
|
|
+ });
|
|
|
+ },
|
|
|
+ });
|
|
|
+ this.modules.push({
|
|
|
+ name: 'fan1RightOpen&fan2LeftOpen',
|
|
|
+ context: group1,
|
|
|
+ behavior: () => {
|
|
|
+ this.stopAnimation(this.elements).then(() => {
|
|
|
+ this.startAnimation([smokeFan1Right, smokeFan2Left, smokeTunnelRight, smokeTunnelMajor]);
|
|
|
+ });
|
|
|
+ },
|
|
|
+ });
|
|
|
+ this.modules.push({
|
|
|
+ name: 'fan2RightOpen&fan2LeftOpen',
|
|
|
+ context: group1,
|
|
|
+ behavior: () => {
|
|
|
+ this.stopAnimation(this.elements).then(() => {
|
|
|
+ this.startAnimation([smokeFan2Right, smokeFan2Left, smokeTunnelRight, smokeTunnelMajor]);
|
|
|
+ });
|
|
|
+ },
|
|
|
+ });
|
|
|
+ // 只有一个风机启动有4种情况
|
|
|
this.modules.push({
|
|
|
name: 'fan1RightOpen',
|
|
|
context: group1,
|
|
|
behavior: () => {
|
|
|
- this.weakElements(this.elements);
|
|
|
- this.startAnimation([smokeFan1Right]);
|
|
|
- this.strongElements([smokeFan1Right]);
|
|
|
+ this.stopAnimation(this.elements).then(() => {
|
|
|
+ this.startAnimation([smokeFan1Right, smokeTunnelMajor]);
|
|
|
+ });
|
|
|
},
|
|
|
});
|
|
|
this.modules.push({
|
|
|
name: 'fan2RightOpen',
|
|
|
context: group1,
|
|
|
behavior: () => {
|
|
|
- this.weakElements(this.elements);
|
|
|
- this.startAnimation([smokeFan2Right]);
|
|
|
- this.strongElements([smokeFan2Right]);
|
|
|
+ this.stopAnimation(this.elements).then(() => {
|
|
|
+ this.startAnimation([smokeFan2Right, smokeTunnelMajor]);
|
|
|
+ });
|
|
|
},
|
|
|
});
|
|
|
this.modules.push({
|
|
|
name: 'fan1LeftOpen',
|
|
|
context: group1,
|
|
|
behavior: () => {
|
|
|
- this.weakElements(this.elements);
|
|
|
- this.startAnimation([smokeFan1Left]);
|
|
|
- this.strongElements([smokeFan1Left]);
|
|
|
+ this.stopAnimation(this.elements).then(() => {
|
|
|
+ this.startAnimation([smokeFan1Left, smokeTunnelRight, smokeTunnelLeft]);
|
|
|
+ });
|
|
|
},
|
|
|
});
|
|
|
this.modules.push({
|
|
|
name: 'fan2LeftOpen',
|
|
|
context: group1,
|
|
|
behavior: () => {
|
|
|
- this.weakElements(this.elements);
|
|
|
- this.startAnimation([smokeFan2Left]);
|
|
|
- this.strongElements([smokeFan2Left]);
|
|
|
+ this.stopAnimation(this.elements).then(() => {
|
|
|
+ this.startAnimation([smokeFan2Left, smokeTunnelRight, smokeTunnelLeft]);
|
|
|
+ });
|
|
|
+ },
|
|
|
+ });
|
|
|
+ }
|
|
|
+
|
|
|
+ /** 初始化css元素,将css元素选择器传入,该方法会将这些元素按顺序放入传入的锚点中 */
|
|
|
+ initCssElement() {
|
|
|
+ const selectors = [
|
|
|
+ {
|
|
|
+ query: '#inputBox2',
|
|
|
+ position: [-90, 9, -10],
|
|
|
},
|
|
|
+ {
|
|
|
+ query: '#inputBox3',
|
|
|
+ position: [-90, 9, 30],
|
|
|
+ },
|
|
|
+ {
|
|
|
+ query: '#T1_1',
|
|
|
+ position: [80, 9, -10],
|
|
|
+ },
|
|
|
+ {
|
|
|
+ query: '#T1_2',
|
|
|
+ position: [20, 9, -10],
|
|
|
+ },
|
|
|
+ {
|
|
|
+ query: '#T2_1',
|
|
|
+ position: [-40, 9, -50],
|
|
|
+ },
|
|
|
+ {
|
|
|
+ query: '#T2_2',
|
|
|
+ position: [30, 9, -50],
|
|
|
+ },
|
|
|
+ {
|
|
|
+ query: '#T3',
|
|
|
+ position: [58, 9, -50],
|
|
|
+ },
|
|
|
+ ];
|
|
|
+ selectors.forEach(({ query, position }, index) => {
|
|
|
+ const element = document.querySelector(query) as HTMLElement;
|
|
|
+ if (element) {
|
|
|
+ const css3D = new CSS3DSprite(element);
|
|
|
+ this.cssSprites.push(css3D);
|
|
|
+ css3D.name = query;
|
|
|
+ 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);
|
|
|
+ css3D.position.set(position[0], position[1], position[2]);
|
|
|
+ this.group?.add(css3D);
|
|
|
+ }
|
|
|
});
|
|
|
}
|
|
|
|
|
|
/** 生成适用于 Smoke 的曲线数据,输入途径点,输出路径,如果是进风类型,首个线段将有扩散效果,出风则是末尾线段有扩散效果 */
|
|
|
- generateSmokePath(points: THREE.Vector3[], airIn?: boolean, airOut?: boolean) {
|
|
|
+ generateSmokePath(namelist: string[], airIn?: boolean, airOut?: boolean) {
|
|
|
+ if (!this.group) return;
|
|
|
const result: any[] = [];
|
|
|
+ const points: THREE.Vector3[] = namelist.map((name) => {
|
|
|
+ const obj = this.group?.getObjectByName(name);
|
|
|
+ return obj?.position as THREE.Vector3;
|
|
|
+ });
|
|
|
for (let index = 1; index < points.length; index++) {
|
|
|
const path0 = points[index - 1];
|
|
|
const path1 = points[index];
|
|
@@ -298,6 +332,10 @@ class ModelContext {
|
|
|
path.isSpread = index === points.length - 1;
|
|
|
path.spreadDirection = 1;
|
|
|
}
|
|
|
+ if (!airIn && !airOut) {
|
|
|
+ path.isSpread = false;
|
|
|
+ path.spreadDirection = 1;
|
|
|
+ }
|
|
|
result.push(path);
|
|
|
}
|
|
|
return result;
|