threlte logo
@threlte/theatre

useSequence

The useSequence hook allows you to access a sequence’s playback controls using a store API.

Usage

The hook can be used within the <Sheet> context or withing the <Sequence> context:

<!-- child of a <Sheet> or <Sequence> -->
<script lang="ts">
  import { useSequence } from '@threlte/theatre'
  const { position, playing, length, play, pause, config } = useSequence()
</script>

Example

This example uses the useSequence hook to allow you to control the feather’s animation using the feather itself. Hover will pause the animation and clicking and dragging the feather up and down allow you to wind back and forth in time.

<script lang="ts">
  import { Canvas } from '@threlte/core'
  import { Project, Sheet } from '@threlte/theatre'

  import Scene from './Scene.svelte'
  import state from './state.json'
</script>

<div>
  <Canvas>
    <Project config={{ state }}>
      <Sheet>
        <Scene />
      </Sheet>
    </Project>
  </Canvas>
</div>

<style>
  div {
    height: 100%;
  }
</style>
<script lang="ts">
  import { T } from '@threlte/core'
  import { GLTF, interactivity } from '@threlte/extras'
  import { SheetObject, useSequence } from '@threlte/theatre'

  interactivity()

  const { play, pause, position, length } = useSequence()

  let baseline: number | undefined = undefined
</script>

<T.Group
  onpointerenter={pause}
  onpointerleave={() => {
    play()
    baseline = undefined
  }}
  onpointerdown={(event) => {
    baseline = event.intersections[0].point.y
  }}
  onpointermove={(event) => {
    if (baseline) {
      const current = event.intersections[0].point.y
      const progress = (baseline - current) / 2
      $position = $position + progress * $length
      baseline = current
    }
  }}
  onpointerup={() => (baseline = undefined)}
>
  <SheetObject key="Feather">
    {#snippet children({ Transform })}
      <Transform>
        <GLTF url="/models/feather.glb" />
      </Transform>
    {/snippet}
  </SheetObject>
</T.Group>
<script lang="ts">
  import { T } from '@threlte/core'
  import { Environment, Text, interactivity } from '@threlte/extras'
  import { useSequence } from '@threlte/theatre'

  import Feather from './Feather.svelte'

  interactivity()

  const { position, config, play } = useSequence()

  // adjust playback settings
  config({ iterationCount: Infinity, rate: 0.3 })

  const format = (num: number) =>
    num.toLocaleString('en-US', {
      minimumFractionDigits: 1,
      maximumFractionDigits: 1
    })

  $: time = format($position)

  play()
</script>

<Feather />

<Text
  position.x={1}
  text={time}
/>

<T.PerspectiveCamera
  position.z={2}
  makeDefault
/>

<T.AmbientLight intensity={0.2} />

<Environment
  url="/textures/equirectangular/hdr/industrial_sunset_puresky_1k.hdr"
  isBackground
/>
{
  "sheetsById": {
    "default": {
      "staticOverrides": {
        "byObject": {
          "Mesh / Transforms": {
            "Position": {
              "x": 0,
              "y": 0.3570440680404296,
              "z": -1.0408340855860843e-17
            }
          },
          "Lights / Main": {
            "Position": {
              "x": 1.4581874883286385,
              "y": 2,
              "z": 1
            }
          },
          "Box / Mesh": {
            "Position": {
              "y": 0
            }
          },
          "Hourglass": {
            "Position": {
              "x": 2.443734229380632,
              "y": 0,
              "z": 2.835536858006085
            },
            "Scale": {
              "x": 0.05,
              "y": 0.05,
              "z": 0.05
            }
          },
          "Cat": {
            "Scale": {
              "x": 0.05,
              "y": 0.05,
              "z": 0.05
            },
            "Position": {
              "x": -2.809109334778998,
              "y": 0,
              "z": -4.164744872672715
            }
          },
          "button": {
            "y": 0,
            "w": false,
            "bold": true
          }
        }
      },
      "sequence": {
        "subUnitsPerUnit": 30,
        "length": 3,
        "type": "PositionalSequence",
        "tracksByObject": {
          "Box / Mesh": {
            "trackData": {
              "b_3bpv4hlh": {
                "type": "BasicKeyframedTrack",
                "__debugName": "Box / Mesh:[\"Position\",\"y\"]",
                "keyframes": [
                  {
                    "id": "CpaIOcSb26",
                    "position": 0,
                    "connectedRight": true,
                    "handles": [0.5, 1, 0.5, 0],
                    "type": "bezier",
                    "value": 0
                  },
                  {
                    "id": "IM4gcoDPhQ",
                    "position": 0.5,
                    "connectedRight": true,
                    "handles": [0.5, 1, 0.5, 0],
                    "type": "bezier",
                    "value": 3
                  },
                  {
                    "id": "eNqDQ7mfVb",
                    "position": 1,
                    "connectedRight": true,
                    "handles": [0.5, 1, 0.5, 0],
                    "type": "bezier",
                    "value": 0
                  }
                ]
              },
              "Es26qfLqOq": {
                "type": "BasicKeyframedTrack",
                "__debugName": "Box / Mesh:[\"Scale\",\"y\"]",
                "keyframes": [
                  {
                    "id": "h4weN9vKxi",
                    "position": 0,
                    "connectedRight": true,
                    "handles": [0.5, 1, 0.5, 0],
                    "type": "bezier",
                    "value": 1
                  },
                  {
                    "id": "PiPY6s5HQj",
                    "position": 0.233,
                    "connectedRight": true,
                    "handles": [0.5, 1, 0.5, 0],
                    "type": "bezier",
                    "value": 1.5
                  },
                  {
                    "id": "XuOoDZU4gN",
                    "position": 0.5,
                    "connectedRight": true,
                    "handles": [0.5, 1, 0.5, 0],
                    "type": "bezier",
                    "value": 1
                  },
                  {
                    "id": "foewgZ636r",
                    "position": 1,
                    "connectedRight": true,
                    "handles": [0.5, 1, 0.5, 0],
                    "type": "bezier",
                    "value": 1
                  }
                ]
              },
              "DIdMVZg5_1": {
                "type": "BasicKeyframedTrack",
                "__debugName": "Box / Mesh:[\"Rotation\",\"x\"]",
                "keyframes": [
                  {
                    "id": "KWyDKX5oLa",
                    "position": 0.4,
                    "connectedRight": true,
                    "handles": [0.5, 1, 0.5, 0],
                    "type": "bezier",
                    "value": 0
                  },
                  {
                    "id": "-LIQQzk5Y6",
                    "position": 0.633,
                    "connectedRight": true,
                    "handles": [0.5, 1, 0.5, 0],
                    "type": "bezier",
                    "value": 90
                  }
                ]
              },
              "2jtXEh_wSh": {
                "type": "BasicKeyframedTrack",
                "__debugName": "Box / Mesh:[\"Rotation\",\"y\"]",
                "keyframes": [
                  {
                    "id": "lHxxYY2-SZ",
                    "position": 0.4,
                    "connectedRight": true,
                    "handles": [0.5, 1, 0.5, 0],
                    "type": "bezier",
                    "value": 0
                  },
                  {
                    "id": "NbRDJ244kN",
                    "position": 0.633,
                    "connectedRight": true,
                    "handles": [0.5, 1, 0.5, 0],
                    "type": "bezier",
                    "value": 90
                  }
                ]
              },
              "--pnqicX6P": {
                "type": "BasicKeyframedTrack",
                "__debugName": "Box / Mesh:[\"Rotation\",\"z\"]",
                "keyframes": [
                  {
                    "id": "SDdqaxukkj",
                    "position": 0.4,
                    "connectedRight": true,
                    "handles": [0.5, 1, 0.5, 0],
                    "type": "bezier",
                    "value": 0
                  },
                  {
                    "id": "Inin2CTeg0",
                    "position": 0.633,
                    "connectedRight": true,
                    "handles": [0.5, 1, 0.5, 0],
                    "type": "bezier",
                    "value": 0
                  }
                ]
              },
              "xcEIo-kPmX": {
                "type": "BasicKeyframedTrack",
                "__debugName": "Box / Mesh:[\"Scale\",\"x\"]",
                "keyframes": []
              },
              "_HEyQtrmLa": {
                "type": "BasicKeyframedTrack",
                "__debugName": "Box / Mesh:[\"Scale\",\"z\"]",
                "keyframes": []
              }
            },
            "trackIdByPropPath": {
              "[\"Position\",\"y\"]": "b_3bpv4hlh",
              "[\"Scale\",\"y\"]": "Es26qfLqOq",
              "[\"Rotation\",\"x\"]": "DIdMVZg5_1",
              "[\"Rotation\",\"y\"]": "2jtXEh_wSh",
              "[\"Rotation\",\"z\"]": "--pnqicX6P",
              "[\"Scale\",\"x\"]": "xcEIo-kPmX",
              "[\"Scale\",\"z\"]": "_HEyQtrmLa"
            }
          },
          "button": {
            "trackData": {
              "zcBh-D8Uq_": {
                "type": "BasicKeyframedTrack",
                "__debugName": "button:[\"x\"]",
                "keyframes": [
                  {
                    "id": "B2xSbyvYpP",
                    "position": 0,
                    "connectedRight": true,
                    "handles": [0.5, 1, 0.5, 0],
                    "type": "bezier",
                    "value": 0
                  },
                  {
                    "id": "xrp-bpABsN",
                    "position": 0.2,
                    "connectedRight": true,
                    "handles": [0.5, 1, 0.5, 0],
                    "type": "bezier",
                    "value": -200
                  },
                  {
                    "id": "BsbFH-RJli",
                    "position": 0.6,
                    "connectedRight": true,
                    "handles": [0.5, 1, 0.5, 0],
                    "type": "bezier",
                    "value": 200
                  },
                  {
                    "id": "hZhY9rtW2l",
                    "position": 0.8,
                    "connectedRight": true,
                    "handles": [0.5, 1, 0.5, 0],
                    "type": "bezier",
                    "value": 0
                  }
                ]
              },
              "odyviKqKB4": {
                "type": "BasicKeyframedTrack",
                "__debugName": "button:[\"y\"]",
                "keyframes": [
                  {
                    "id": "EZc_TOnB8l",
                    "position": 0,
                    "connectedRight": true,
                    "handles": [0.5, 1, 0.5, 0],
                    "type": "bezier",
                    "value": 0
                  },
                  {
                    "id": "k4d5KSMm3S",
                    "position": 0.1,
                    "connectedRight": true,
                    "handles": [0.5, 1, 0.5, 0],
                    "type": "bezier",
                    "value": -50
                  },
                  {
                    "id": "xQWcr8pHxG",
                    "position": 0.3,
                    "connectedRight": true,
                    "handles": [0.5, 1, 0.5, 0],
                    "type": "bezier",
                    "value": 50
                  },
                  {
                    "id": "g7zdL4auIV",
                    "position": 0.5,
                    "connectedRight": true,
                    "handles": [0.5, 1, 0.5, 0],
                    "type": "bezier",
                    "value": -50
                  },
                  {
                    "id": "62GD2tlQvM",
                    "position": 0.7,
                    "connectedRight": true,
                    "handles": [0.5, 1, 0.5, 0],
                    "type": "bezier",
                    "value": 50
                  },
                  {
                    "id": "yCTiQlHoj1",
                    "position": 0.9,
                    "connectedRight": true,
                    "handles": [0.5, 1, 0.5, 0],
                    "type": "bezier",
                    "value": 0
                  }
                ]
              },
              "6P6ha6na9e": {
                "type": "BasicKeyframedTrack",
                "__debugName": "button:[\"bold\"]",
                "keyframes": [
                  {
                    "id": "kl7MVNMl-Y",
                    "position": 0,
                    "connectedRight": true,
                    "handles": [0.5, 1, 0.5, 0],
                    "type": "bezier",
                    "value": false
                  },
                  {
                    "id": "GlgZf6996q",
                    "position": 0.9,
                    "connectedRight": true,
                    "handles": [0.5, 1, 0.5, 0],
                    "type": "bezier",
                    "value": true
                  },
                  {
                    "id": "xaWNVuJc3B",
                    "position": 1,
                    "connectedRight": true,
                    "handles": [0.5, 1, 0.5, 0],
                    "type": "bezier",
                    "value": true
                  }
                ]
              }
            },
            "trackIdByPropPath": {
              "[\"x\"]": "zcBh-D8Uq_",
              "[\"y\"]": "odyviKqKB4",
              "[\"bold\"]": "6P6ha6na9e"
            }
          },
          "Feather": {
            "trackData": {
              "XFWRBWGCYD": {
                "type": "BasicKeyframedTrack",
                "__debugName": "Feather:[\"position\",\"x\"]",
                "keyframes": []
              },
              "3i48L_UXaD": {
                "type": "BasicKeyframedTrack",
                "__debugName": "Feather:[\"position\",\"y\"]",
                "keyframes": [
                  {
                    "id": "1fcUkLkxf3",
                    "position": 0,
                    "connectedRight": true,
                    "handles": [0.5, 1, 0.12825278810408913, 0.12136219682258331],
                    "type": "bezier",
                    "value": 2
                  },
                  {
                    "id": "nXzSEOZ5rG",
                    "position": 3,
                    "connectedRight": true,
                    "handles": [0.7973977695167287, 0.7989938615125962, 0.5, 0],
                    "type": "bezier",
                    "value": -2
                  }
                ]
              },
              "xoXXb0Gj6w": {
                "type": "BasicKeyframedTrack",
                "__debugName": "Feather:[\"position\",\"z\"]",
                "keyframes": []
              }
            },
            "trackIdByPropPath": {
              "[\"position\",\"x\"]": "XFWRBWGCYD",
              "[\"position\",\"y\"]": "3i48L_UXaD",
              "[\"position\",\"z\"]": "xoXXb0Gj6w"
            }
          }
        }
      }
    }
  },
  "definitionVersion": "0.4.0",
  "revisionHistory": [
    "9oKH4i0sbUCjnC12",
    "jn9FHXpLtlURzWOs",
    "qpo86xX0z9LVRsoV",
    "62cBnS0EMiw9EDzl",
    "WdqDOLSNW-TCSoDz",
    "ZxoPi9jfsYCHwP__"
  ]
}

Output

The following values are returned by the hook:

storetypedescription
lengthnumberThe length of the sequence, which is set within the studio
positionWritable<number>The sequence playhead position
playingWritable<boolean>The sequence state (playing or paused)
play(opts?: SequenceOptions) => Promise<boolean>Method for playing the sequence
pause() => voidMethod for pausing the sequence
config(opts: SequenceOptions) => voidMethod for updating the sequence’s options