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