angular8+threejs 如何架构项目+分离模型+模型动画调用+动画暂停/继续

原因:threejs在运用的时候因为是没有html全都是js,所以我想把每个模型都分成不同的service来处理,而且事件也分离到自己的service里面

附加模型下载地址:传送门
结构事例(有点乱没整理求不要骂)

image.png

下面直接上代码吧

1、新建ng项目(不多说了);

2、新建一个base.ts (angular8+threejs 入坑文中有详细说明),主要是用于存放一些threejs场景的基本元素:渲染器、场景、灯光、相机、网格、性能检测 和 主要画布的搭建

image.png

3、新建一个skeleton.service(这里面包括了骨骼、模型的动画调用)

import { Injectable } from '@angular/core';
import { SkeletonHelper, AnimationMixer, Clock, AnimationAction} from 'three';
import { SCENE} from '../config/base';
import { GLTFLoader } from 'three-full';
@Injectable({
 providedIn: 'root'
})
export class SkeletonService {
 action: AnimationAction;  // 动画动作
 constructor() {
 }

 /**
  * @ name 控制动画开始和暂停
  * @ param e 回调开关
  */
 isPlay(e: boolean) {
   this.action.paused = e;
 }

 addSkeleton() {
   let mixer;

   const loader = new GLTFLoader();
   loader.load('assets/model/people/CesiumMan.glb', (gltf) => {

     // 把模型添加到场景中,SCENE是从base.ts导入的
     SCENE.add(gltf.scene);

     // 显示模型骨架
     const skeletonHelper = new SkeletonHelper(gltf.scene);
     skeletonHelper.material['linewidth'.toString()] = 2;
     SCENE.add(skeletonHelper);

     // 调用模型动画
     mixer = new AnimationMixer(gltf.scene);
     this.action = mixer.clipAction(gltf.animations[0]); //  gltf.animations[0]模型里面的第一个动作
     this.action.play(); //  必须要play()动画才会播放

     //  监听单个动画结束回调
     mixer.addEventListener('loop', (e) => {
       console.log(e);
       console.log('结束');

     });
   },
     undefined,
     (error) => {
       console.error(error);
     });

   //  定义时间,这个必须要写在const render 的外面,因为render是不停刷新的如果写在里面会不停重置
   const delta = new Clock();

   //  本模型的渲染事件可以分离到这里
   const render = () => {
     requestAnimationFrame(render);

     // RENDERER.render(SCENE, CAMERA);  这个 只需要写在canva.ts那边就可以了,这边不用写

     if (mixer) {
       mixer.update(delta.getDelta());
     }

   };
   render();
 }



}
image.png
image.png

4、回到canva的init() 直接调用 skeleton.service.ts 的 addSkeleton(); 就可以运行了

5、给模型添加动作的暂停开始操作

canva.html(可能会出现看不到按钮的情况,注意设置浮动)

 

canva.ts

play = false;
player() {
this.play = !this.play;
this.sk.isPlay(this.play); //  调用skeleton.service.ts 的方法
}

点击按钮就可以控制动画的继续和暂停了

总结:这样就可以把事件和模型单独分离成多个ts了,不会导致代码混乱,如果有更好的方法欢迎大家留言讨论


2019.08.19更改
文中skeleton.service 里面有个地方写得不对


image.png

就是动画更新这块,这个不应该写在这里,应为在多个文件进行requestAnimationFrame的画性能会有影响,性能显示不平滑,出现锯齿状。
image.png

解决办法:可以定义一个全局变量,然后去canvas那边统一进行更新。

你可能感兴趣的:(angular8+threejs 如何架构项目+分离模型+模型动画调用+动画暂停/继续)