You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何通过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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.31 23:36:37