|
|
|
|
import type Viewer from "../Viewer";
|
|
|
|
|
import { GUI } from "three/examples/jsm/libs/lil-gui.module.min";
|
|
|
|
|
import * as THREE from "three";
|
|
|
|
|
|
|
|
|
|
class Params {
|
|
|
|
|
x: number = 0;
|
|
|
|
|
y: number = 0;
|
|
|
|
|
z: number = 100;
|
|
|
|
|
size: number = 3;
|
|
|
|
|
length: number = 10;
|
|
|
|
|
radius: number = 16;
|
|
|
|
|
visible: boolean = true;
|
|
|
|
|
widthSegments: number = 64;
|
|
|
|
|
heightSegments: number = 32;
|
|
|
|
|
color: string = "#000";
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
export default class Earth {
|
|
|
|
|
protected viewer: Viewer;
|
|
|
|
|
public particles_init_position!: number;
|
|
|
|
|
public zprogress!: number; // 声明点在z轴上移动的进度
|
|
|
|
|
public zprogress_second!: number; // 声明同上(第二个几何点)
|
|
|
|
|
public particles_first!: any[]; // 声明粒子1
|
|
|
|
|
public particles_second!: any[]; // 声明粒子1
|
|
|
|
|
public parameters!: any; // 声明点的参数
|
|
|
|
|
public materials!: any[]; // 声明点材质
|
|
|
|
|
public cloudParameter_first!: any; // 声明流动的云对象1(包含路径、云实例)
|
|
|
|
|
public cloudParameter_second!: any; // 声明流动的云对象2(包含路径、云实例)
|
|
|
|
|
public renderCloudMove_first!: any; // 声明云流动的渲染函数1
|
|
|
|
|
public renderCloudMove_second!: any; // 声明云流动的渲染函数1
|
|
|
|
|
public gui!: any; // 声明调试工具
|
|
|
|
|
|
|
|
|
|
constructor(viewer: Viewer) {
|
|
|
|
|
this.viewer = viewer;
|
|
|
|
|
this.materials = [];
|
|
|
|
|
this.gui = new GUI();
|
|
|
|
|
this.particles_init_position = -this.viewer.zAxisNumber - this.viewer.depth / 2;
|
|
|
|
|
this.zprogress = this.particles_init_position;
|
|
|
|
|
this.zprogress_second = this.particles_init_position * 2;
|
|
|
|
|
this.particles_first = this.initSceneStar(this.particles_init_position);
|
|
|
|
|
this.particles_second = this.initSceneStar(this.zprogress_second);
|
|
|
|
|
this.cloudParameter_first = this.initTubeRoute(
|
|
|
|
|
[
|
|
|
|
|
new THREE.Vector3(-this.viewer.viewerDom.clientWidth / 10, 0, -this.viewer.depth / 2),
|
|
|
|
|
new THREE.Vector3(-this.viewer.viewerDom.clientWidth / 4, this.viewer.viewerDom.clientHeight / 8, 0),
|
|
|
|
|
new THREE.Vector3(-this.viewer.viewerDom.clientWidth / 4, 0, this.viewer.zAxisNumber)
|
|
|
|
|
],
|
|
|
|
|
400,
|
|
|
|
|
200
|
|
|
|
|
);
|
|
|
|
|
this.cloudParameter_second = this.initTubeRoute(
|
|
|
|
|
[
|
|
|
|
|
new THREE.Vector3(this.viewer.viewerDom.clientWidth / 8, this.viewer.viewerDom.clientHeight / 8, -this.viewer.depth / 2),
|
|
|
|
|
new THREE.Vector3(this.viewer.viewerDom.clientWidth / 8, this.viewer.viewerDom.clientHeight / 8, this.viewer.zAxisNumber)
|
|
|
|
|
],
|
|
|
|
|
200,
|
|
|
|
|
100
|
|
|
|
|
);
|
|
|
|
|
this.renderCloudMove_first = this.initCloudMove(this.cloudParameter_first, 0.0002);
|
|
|
|
|
this.renderCloudMove_second = this.initCloudMove(this.cloudParameter_second, 0.0008, 0.001);
|
|
|
|
|
this.initGUI();
|
|
|
|
|
|
|
|
|
|
const animate = () => {
|
|
|
|
|
if (this.viewer.isDestroy) return;
|
|
|
|
|
requestAnimationFrame(animate);
|
|
|
|
|
this.renderStarMove();
|
|
|
|
|
this.renderCloudMove_first();
|
|
|
|
|
this.renderCloudMove_second();
|
|
|
|
|
this.viewer.updateDom();
|
|
|
|
|
this.viewer.renderDom();
|
|
|
|
|
};
|
|
|
|
|
animate();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 初始化gui
|
|
|
|
|
public initGUI = () => {
|
|
|
|
|
const params = new Params();
|
|
|
|
|
this.gui.add(params, "x", -1500, 1500).onChange((x: number) => {
|
|
|
|
|
//点击颜色面板,e为返回的10进制颜色
|
|
|
|
|
this.viewer.Sphere_Group.position.x = x;
|
|
|
|
|
});
|
|
|
|
|
this.gui.add(params, "y", -50, 1500).onChange((y: number) => {
|
|
|
|
|
//点击颜色面板,e为返回的10进制颜色
|
|
|
|
|
this.viewer.Sphere_Group.position.y = y;
|
|
|
|
|
});
|
|
|
|
|
this.gui.add(params, "z", -200, 1000).onChange((z: number) => {
|
|
|
|
|
//点击颜色面板,e为返回的10进制颜色
|
|
|
|
|
this.viewer.Sphere_Group.position.z = z;
|
|
|
|
|
});
|
|
|
|
|
// this.gui.add(params, "widthSegments", 0, 64).onChange((widthSegments: number) => {
|
|
|
|
|
// //点击颜色面板,e为返回的10进制颜色
|
|
|
|
|
// // this.viewer.sphereGeometry.parameters.widthSegments = widthSegments;
|
|
|
|
|
// });
|
|
|
|
|
// this.gui.add(params, "heightSegments", 0, 32).onChange((heightSegments: number) => {
|
|
|
|
|
// //点击颜色面板,e为返回的10进制颜色
|
|
|
|
|
// // this.viewer.sphereGeometry.parameters.heightSegments = heightSegments;
|
|
|
|
|
// });
|
|
|
|
|
// this.gui.add(params, "radius", 5, 30).onChange((radius: number) => {
|
|
|
|
|
// //点击颜色面板,e为返回的10进制颜色
|
|
|
|
|
// // this.viewer.sphereGeometry.parameters.radius = radius;
|
|
|
|
|
// this.viewer.renderer.render(this.viewer.scene, this.viewer.camera);
|
|
|
|
|
// });
|
|
|
|
|
// this.gui.add(params, "visible").onChange((e: any) => {
|
|
|
|
|
// //这是一个单选框,因为params.visible是一个布尔值,e返回所选布尔值
|
|
|
|
|
// // points.visible = e
|
|
|
|
|
// });
|
|
|
|
|
// this.gui.addColor(params, "color").onChange((e: any) => {
|
|
|
|
|
// //点击颜色面板,e为返回的10进制颜色
|
|
|
|
|
// // pointsMaterial.color.set(e)
|
|
|
|
|
// });
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
private initSceneStar(initZposition: number) {
|
|
|
|
|
const geometry = new THREE.BufferGeometry();
|
|
|
|
|
const vertices: number[] = [];
|
|
|
|
|
const pointsGeometry: any[] = [];
|
|
|
|
|
const textureLoader = new THREE.TextureLoader();
|
|
|
|
|
const sprite1 = textureLoader.load("/images/starflake1.png");
|
|
|
|
|
const sprite2 = textureLoader.load("/images/starflake2.png");
|
|
|
|
|
this.parameters = [
|
|
|
|
|
[[0.6, 100, 0.75], sprite1, 50],
|
|
|
|
|
[[0, 0, 1], sprite2, 20]
|
|
|
|
|
];
|
|
|
|
|
// 初始化500个节点
|
|
|
|
|
for (let i = 0; i < 500; i++) {
|
|
|
|
|
/**
|
|
|
|
|
* const x: number = Math.random() * 2 * width - width
|
|
|
|
|
* 等价
|
|
|
|
|
* THREE.MathUtils.randFloatSpread(width)
|
|
|
|
|
*/
|
|
|
|
|
const x: number = THREE.MathUtils.randFloatSpread(this.viewer.viewerDom.clientWidth);
|
|
|
|
|
const y: number = _.random(0, this.viewer.viewerDom.clientHeight / 2);
|
|
|
|
|
const z: number = _.random(-this.viewer.depth / 2, this.viewer.zAxisNumber);
|
|
|
|
|
vertices.push(x, y, z);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
geometry.setAttribute("position", new THREE.Float32BufferAttribute(vertices, 3));
|
|
|
|
|
// 创建2种不同的材质的节点(500 * 2)
|
|
|
|
|
for (let i = 0; i < this.parameters.length; i++) {
|
|
|
|
|
const color = this.parameters[i][0];
|
|
|
|
|
const sprite = this.parameters[i][1];
|
|
|
|
|
const size = this.parameters[i][2];
|
|
|
|
|
|
|
|
|
|
this.materials[i] = new THREE.PointsMaterial({
|
|
|
|
|
size,
|
|
|
|
|
map: sprite,
|
|
|
|
|
blending: THREE.AdditiveBlending,
|
|
|
|
|
depthTest: true,
|
|
|
|
|
transparent: true
|
|
|
|
|
});
|
|
|
|
|
this.materials[i].color.setHSL(color[0], color[1], color[2]);
|
|
|
|
|
const particles = new THREE.Points(geometry, this.materials[i]);
|
|
|
|
|
particles.rotation.x = Math.random() * 0.2 - 0.15;
|
|
|
|
|
particles.rotation.z = Math.random() * 0.2 - 0.15;
|
|
|
|
|
particles.rotation.y = Math.random() * 0.2 - 0.15;
|
|
|
|
|
particles.position.setZ(initZposition);
|
|
|
|
|
pointsGeometry.push(particles);
|
|
|
|
|
this.viewer.scene.add(particles);
|
|
|
|
|
}
|
|
|
|
|
return pointsGeometry;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 渲染星星的运动
|
|
|
|
|
public renderStarMove() {
|
|
|
|
|
const time = Date.now() * 0.00005;
|
|
|
|
|
this.zprogress += 1;
|
|
|
|
|
this.zprogress_second += 1;
|
|
|
|
|
|
|
|
|
|
if (this.zprogress >= this.viewer.zAxisNumber + this.viewer.depth / 2) {
|
|
|
|
|
this.zprogress = this.particles_init_position;
|
|
|
|
|
} else {
|
|
|
|
|
this.particles_first.forEach((item) => {
|
|
|
|
|
item.position.setZ(this.zprogress);
|
|
|
|
|
});
|
|
|
|
|
}
|
|
|
|
|
if (this.zprogress_second >= this.viewer.zAxisNumber + this.viewer.depth / 2) {
|
|
|
|
|
this.zprogress_second = this.particles_init_position;
|
|
|
|
|
} else {
|
|
|
|
|
this.particles_second.forEach((item) => {
|
|
|
|
|
item.position.setZ(this.zprogress_second);
|
|
|
|
|
});
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
for (let i = 0; i < this.materials.length; i++) {
|
|
|
|
|
const color = this.parameters[i][0];
|
|
|
|
|
|
|
|
|
|
const h = ((360 * (color[0] + time)) % 360) / 360;
|
|
|
|
|
this.materials[i].color.setHSL(color[0], color[1], parseFloat(h.toFixed(2)));
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 初始化云的运动函数
|
|
|
|
|
public initCloudMove = (cloudParameter: any, speed: number, scaleSpeed = 0.0006, maxScale = 1, startScale = 0) => {
|
|
|
|
|
let cloudProgress = 0;
|
|
|
|
|
return () => {
|
|
|
|
|
if (startScale < maxScale) {
|
|
|
|
|
startScale += scaleSpeed;
|
|
|
|
|
cloudParameter.cloud.scale.setScalar(startScale);
|
|
|
|
|
}
|
|
|
|
|
if (cloudProgress > 1) {
|
|
|
|
|
cloudProgress = 0;
|
|
|
|
|
startScale = 0;
|
|
|
|
|
} else {
|
|
|
|
|
cloudProgress += speed;
|
|
|
|
|
if (cloudParameter.curve) {
|
|
|
|
|
const point = cloudParameter.curve.getPoint(cloudProgress);
|
|
|
|
|
if (point && point.x) {
|
|
|
|
|
cloudParameter.cloud.position.set(point.x, point.y, point.z);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
};
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
// 初始化流动路径
|
|
|
|
|
private initTubeRoute(route?: any, geometryWidth?: number, geometryHeigh?: number) {
|
|
|
|
|
const curve = new THREE.CatmullRomCurve3(route, false);
|
|
|
|
|
const tubeGeometry = new THREE.TubeGeometry(curve, 100, 2, 50, false);
|
|
|
|
|
const tubeMaterial = new THREE.MeshBasicMaterial({
|
|
|
|
|
// color: '0x4488ff',
|
|
|
|
|
opacity: 0,
|
|
|
|
|
transparent: true
|
|
|
|
|
});
|
|
|
|
|
const tube = new THREE.Mesh(tubeGeometry, tubeMaterial);
|
|
|
|
|
this.viewer.scene.add(tube);
|
|
|
|
|
|
|
|
|
|
const clondGeometry = new THREE.PlaneGeometry(geometryWidth, geometryHeigh);
|
|
|
|
|
const textureLoader = new THREE.TextureLoader();
|
|
|
|
|
const cloudTexture = textureLoader.load("/images/cloud.png");
|
|
|
|
|
const clondMaterial = new THREE.MeshBasicMaterial({
|
|
|
|
|
map: cloudTexture,
|
|
|
|
|
blending: THREE.AdditiveBlending,
|
|
|
|
|
depthTest: false,
|
|
|
|
|
transparent: true
|
|
|
|
|
});
|
|
|
|
|
const cloud = new THREE.Mesh(clondGeometry, clondMaterial);
|
|
|
|
|
this.viewer.scene.add(cloud);
|
|
|
|
|
return { cloud, curve };
|
|
|
|
|
}
|
|
|
|
|
}
|