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