现在的很多建模软件都可以制作动画效果,甚至可以通过各种动画效果直接做动漫,动漫是模型的一种属性,在threejs中同样可以加载此动画,实现动画效果,如果有的时候在threejs中用代码实现模型动画比较困难或者麻烦,可以在模型中做好动画,然后在threejs中通过代码播放此动画来实现,
如果想看一个模型有几个动画可以在加载模型后打印出来明细查看
const loader = new GLTFLoader()loader.load("/static/cartoon/scene.gltf", (gltf) => {this.women = gltf.scene;this.women.position.set(0, 0, 0) // 模型位置this.women.scale.set(1,1,1)scene.add(this.women) // 加入场景console.log(gltf)
})
如图,这里的animations就是动画集合,这里可以看到此模型有1个动画,
但是此时只是把模型加载进去不会自动播放模型自带的动画,只是一个静止的模型而已,需要动画播放需要加载动画并播放。
然后根据这个动画调用动画的组件去播放这部分在之前的关键帧动画中有相关用到,这里是模型自带的就不需要做动画设置了
initRound(){//在场景中加载一个agv小车,并将agv小车放在曲线的第一个点上const loader = new GLTFLoader()loader.load("/static/cartoon/scene.gltf", (gltf) => {this.women = gltf.scene;this.women.position.set(0, 0, 0) // 模型位置this.women.scale.set(1,1,1)scene.add(this.women) // 加入场景console.log(gltf)this.mixer = new THREE.AnimationMixer(this.women);const action = this.mixer.clipAction(gltf.animations[0])//把该物体需要的动画拿出来action.setLoop(THREE.LoopOnce);//设置只播放一次,THREE.LoopRepeat设置播放多次action.play();})},
同时也还是要在最后渲染的时候不断更新动画
initAnimate() {if(this.mixer){this.mixer.update(0.0166666666);//这里给动画设置更新速度,因为默认是一秒钟渲染60次,所以这里设置为1/60的值,}requestAnimationFrame(this.initAnimate);this.renderer.render(scene, this.camera);},
完整的代码如下:
<template><div><div id="container"></div></div>
</template><script>
import * as THREE from 'three'
import {OrbitControls} from "three/addons/controls/OrbitControls";
import {GLTFLoader} from "three/addons/loaders/GLTFLoader";let scene;
export default {name: "agv-single",data() {return{camera:null,cameraCurve:null,renderer:null,container:null,controls:null,pathIndex:0,//小车的运动轨迹点索引women:null,mixer:null,}},methods:{initScene(){scene = new THREE.Scene();},initCamera(){this.camera = new THREE.PerspectiveCamera(45, window.innerWidth / window.innerHeight, 0.1, 10000);this.camera.position.set(10,10,10);},initLight(){//添加两个平行光const directionalLight1 = new THREE.DirectionalLight(0xffffff, 1.5);directionalLight1.position.set(-300,-300,600)scene.add(directionalLight1);const directionalLight2 = new THREE.DirectionalLight(0xffffff, 1.5);directionalLight2.position.set(600,200,600)scene.add(directionalLight2);},initRound(){//在场景中加载一个agv小车,并将agv小车放在曲线的第一个点上const loader = new GLTFLoader()loader.load("/static/cartoon/scene.gltf", (gltf) => {this.women = gltf.scene;this.women.position.set(0, 0, 0) // 模型位置this.women.scale.set(1,1,1)scene.add(this.women) // 加入场景console.log(gltf)this.mixer = new THREE.AnimationMixer(this.women);const action = this.mixer.clipAction(gltf.animations[0])//把该物体需要的动画拿出来action.setLoop(THREE.LoopOnce);//设置只播放一次,THREE.LoopRepeat设置播放多次action.play();})},initRenderer(){this.renderer = new THREE.WebGLRenderer({ antialias: true });this.container = document.getElementById("container")this.renderer.setSize(this.container.clientWidth, this.container.clientHeight);this.renderer.setClearColor('#AAAAAA', 1.0);this.container.appendChild(this.renderer.domElement);},initControl(){this.controls = new OrbitControls(this.camera, this.renderer.domElement);this.controls.enableDamping = true;this.controls.maxPolarAngle = Math.PI / 2.2; // // 最大角度},initAnimate() {if(this.mixer){this.mixer.update(0.0166666666);//这里给动画设置更新速度,因为默认是一秒钟渲染60次,所以这里设置为1/60的值,}requestAnimationFrame(this.initAnimate);this.renderer.render(scene, this.camera);},initPage(){this.initScene();this.initCamera();this.initLight();this.initRenderer();this.initControl();this.initRound();this.initAnimate();}},mounted() {this.initPage()}
}
</script><style scoped>
#container{position: absolute;width:100%;height:100%;overflow: hidden;
}</style>
效果如下:
模型自带动画