threlte logo
@threlte/extras

useGltfAnimations

Convenience hook to use animations loaded with a <GLTF> Threlte component.

<script lang="ts">
  import { Canvas } from '@threlte/core'
  import Scene from './Scene.svelte'
</script>

<Canvas>
  <Scene />
</Canvas>
<script lang="ts">
  import { T, useThrelte } from '@threlte/core'
  import { OrbitControls } from '@threlte/extras'
  import { Color } from 'three'
  import Tokyo from './Tokyo.svelte'

  const { scene } = useThrelte()
  scene.background = new Color(0xeae8e2)

  let showTokyo = true
</script>

<svelte:window
  on:keypress={() => {
    showTokyo = !showTokyo
  }}
/>

<T.PerspectiveCamera
  makeDefault
  position={[600, 200, 600]}
  near={10}
  far={10000}
>
  <OrbitControls
    autoRotate
    autoRotateSpeed={0.2}
    enableDamping
    enableZoom={false}
    target={[-60, -75, 0]}
  />
</T.PerspectiveCamera>

<T.AmbientLight />
<T.DirectionalLight position={[5, 10, 5]} />

{#if showTokyo}
  <Tokyo />
{/if}
<script lang="ts">
  import { GLTF, useGltfAnimations } from '@threlte/extras'

  const { gltf, actions } = useGltfAnimations<'Take 001'>()

  $: $actions['Take 001']?.play()
</script>

<GLTF
  bind:gltf={$gltf}
  url="/models/LittlestTokyo.glb"
  useDraco="https://www.gstatic.com/draco/v1/decoders/"
/>

Model: Littlest Tokyo by Glen Fox, CC Attribution.

Examples

Basic Example

<script lang="ts">
  import { GLTF, useGltfAnimations } from '@threlte/extras'
  // `useGltfAnimations` returns stores that populate
  // when the `<GLTF>` component finished loading.
  const { gltf, actions, mixer } = useGltfAnimations<'All Animations'>()

  // Play them whenever you need
  export const triggerAnimation = () => {
    if ($mixer) $mixer.timeScale = 0.5
    $actions['All Animations']?.play()
  }
</script>

<!-- Bind the store `gltf` -->
<GLTF
  url={'/Bengal.glb'}
  bind:gltf={$gltf}
/>

Using the useGltf Hook

Sometimes you might want to use the hook useGltf to reuse parts of a model or use the embedded camera. In this case, the hook useGltf returns an object with a property gltf which you can pass as the first argument to the hook useGltfAnimations.

<script lang="ts">
  import { T } from '@threlte/core'
  import { useGltfAnimations, useGltf } from '@threlte/extras'

  // In this example, the useGltf hook returns a Writable<THREE.GLTF> store
  const gltf = useGltf('/path/to/model.glb')

  // Provide that store to the hook useGltfAnimations
  useGltfAnimations<'All Animations'>(gltf)

  // play the animation as soon as it's loaded
  $: $actions['All Animations']?.play()
</script>

{#if $gltf}
  <T is={$gltf.scene} />
{/if}

Applying animations to a different root

Sometimes you want to apply the animations to a different root than the GLTF scene. In this case, pass the root as the second argument to the hook useGltfAnimations.

<script>
  import { useGltfAnimations, useGltf } from '@threlte/extras'
  import { Group } from 'three'

  const gltf = useGltf('/path/to/model.glb')

  const group = new Group()

  const { root } = useGltfAnimations(gltf, group)
</script>

{#if $gltf}
  <T is={group}>
    <T is={$gltf.scene}>
  </T>
{/if}

This can also be done after the animations have been loaded. In this case, you can use the bind:ref directive to bind the root to the root store returned by the hook.

<script>
  import { useGltfAnimations, useGltf } from '@threlte/extras'
  import { Group } from 'three'

  const gltf = useGltf('/path/to/model.glb')

  const { root } = useGltfAnimations(gltf, group)
</script>

{#if $gltf}
  <T.Group bind:ref={$root}>
    <T is={$gltf.scene}>
  </T>
{/if}

Types

const {
  gltf, // Writable<GLTF | undefined>
  mixer, // AnimationMixer
  actions, // CurrentWritable<Record<string, AnimationAction>>
  root // CurrentWritable<Root | undefined>
} = useGLtfAnimations()