如何通过Three.js控制A-FRAME中.glb模型动画 解决动画仅播1秒停止问题
问题根因
动画仅播放1秒就停止是代码逻辑存在3个核心问题:
- 仅在
setTimeout回调中执行了一次mixer.update(delta),Three.js的动画混合器需要每帧根据时间差更新状态才能持续推进动画,单次调用只会渲染极短的动画片段 - 用固定2秒延时等待模型加载不可靠,网络波动时模型未加载完成就执行逻辑,会出现拿不到模型、动画资源的报错
- 创建的
AnimationMixer、Clock实例都定义在setTimeout的局部作用域中,后续逻辑无法访问这些实例,根本做不到持续更新
修复后完整代码
<script src="https://aframe.io/releases/1.3.0/aframe.min.js"></script> <script> AFRAME.registerComponent('play-model-anim', { init: function () { // 监听模型加载完成事件,替代固定延时等待 this.el.addEventListener('model-loaded', () => { const model = this.el.components['gltf-model'].model // 将核心实例绑定到组件实例上,供帧循环访问 this.mixer = new THREE.AnimationMixer(model) this.clock = new THREE.Clock() // 初始化动画动作,显式设置无限循环 const animAction = this.mixer.clipAction(model.animations[0]) animAction.setLoop(THREE.LoopRepeat, Infinity) animAction.play() }) }, // A-Frame组件原生帧循环钩子,每帧自动执行 tick: function () { if (!this.mixer || !this.clock) return const deltaTime = this.clock.getDelta() this.mixer.update(deltaTime) } }) </script> <a-scene> <a-entity gltf-model="https://rawcdn.githack.com/BabylonJS/MeshesLibrary/55f475726670be2e7e4017b5f88c5762a90508c2/shark.glb" play-model-anim position=".5 0.5 -5" scale="0.5 0.5 0.5"> </a-entity> </a-scene>
关键改动说明
- 弃用固定时长的
setTimeout,改用gltf-model组件提供的model-loaded事件触发初始化逻辑,保证模型、动画资源完全就绪后再创建动画混合器,不会出现资源为空的问题 - 将
AnimationMixer、Clock实例挂载到组件实例this上,避免局部作用域销毁后实例无法访问 - 利用A-Frame组件自带的
tick生命周期实现帧循环,每帧自动计算时间差更新动画混合器,保证动画持续流畅播放 - 显式设置动画为无限循环模式,规避部分glb文件导出时默认不开启循环的问题
- 移除了原代码中无意义的0.25倍速系数,动画会按模型导出时的原始速度播放,需要调整播放速度可以给
deltaTime乘上对应倍数值即可,比如0.5倍速就写this.mixer.update(deltaTime * 0.5)
内容的提问来源于stack exchange,提问作者Frank Leaster
相关产品推荐
相关产品推荐

