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

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);
}
}