You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
salary-management-oneself/src/lib/three/Viewer/index.ts

101 lines
2.9 KiB
TypeScript

This file contains ambiguous Unicode characters!

This file contains ambiguous Unicode characters that may be confused with others in your current locale. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to highlight these characters.

import { AxesHelper, Camera, PerspectiveCamera, Scene, WebGLRenderer } from "three";
import { OrbitControls } from "three/examples/jsm/controls/OrbitControls";
export type Animate = {
fun: (arg: any) => any;
content: any;
};
export default class Viewer {
public id: string;
public viewerDom!: HTMLElement;
public renderer!: WebGLRenderer;
public scene!: Scene;
public camera!: PerspectiveCamera;
public controls!: OrbitControls;
public isDestroy = false; // 是否销毁
public animateEventList = new Map();
constructor(id: string) {
this.id = id;
this.initViewer();
}
private initViewer() {
this.initRender();
this.initScene();
this.initCamera();
this.initControl();
const animate = () => {
if (this.isDestroy) return;
requestAnimationFrame(animate);
this.updateDom();
this.renderDom();
// 全局的公共动画函数,添加函数可同步执行
this.animateEventList.forEach((event) => {
if (event.fun && event.content) event.fun(event.content);
});
};
animate();
}
private initRender() {
// 获取画布dom
this.viewerDom = document.getElementById(this.id) as HTMLElement;
this.renderer = new WebGLRenderer({ antialias: true });
this.viewerDom.appendChild(this.renderer.domElement);
}
// 创建场景
private initScene() {
this.scene = new Scene();
}
private initControl() {
this.controls = new OrbitControls(this.camera as Camera, this.renderer?.domElement);
this.controls.enableDamping = false;
this.controls.screenSpacePanning = false;
this.controls.minDistance = 2;
this.controls.maxDistance = 1000;
}
// 初始化相机
public initCamera() {
this.camera = new PerspectiveCamera(75, this.viewerDom.clientWidth / this.viewerDom.clientHeight, 0.1, 1000);
this.camera.position.set(5, 5, 10);
this.camera.lookAt(0, 0, 0);
}
//创建坐标轴辅助对象
public addAxis() {
const axis = new AxesHelper(1000);
this.scene?.add(axis);
}
// 添加动画事件
public addAnimate(id: string, animate: Animate) {
this.animateEventList.set(id, animate);
}
// 根据传入的id删除动画事件列表中的对应事件
public removeAnimate(id: string) {
this.animateEventList?.delete(id);
}
// 更新参数
public updateDom() {
this.camera.aspect = this.viewerDom.clientWidth / this.viewerDom.clientHeight; // 摄像机视锥体的长宽比,通常是使用画布的宽/画布的高
this.camera.updateProjectionMatrix(); // 更新摄像机投影矩阵。在任何参数被改变以后必须被调用,来使得这些改变生效
this.renderer.setSize(this.viewerDom.clientWidth, this.viewerDom.clientHeight);
this.renderer.setPixelRatio(window.devicePixelRatio); // 设置设备像素比
}
// 渲染dom
public renderDom() {
this.renderer?.render(this.scene as Scene, this.camera as Camera);
}
}