threlte logo
@threlte/theatre

sheetObjectAction

When Theatre.js represents the animated elements on a page as Sheet Objects which have props you can animate. A Sheet Object can be a ThreeJS element or a DOM element.

The createSheetObjectAction hook allows you to animate DOM elements through a Svelte Action.

Theatre.js Docs

   
Sheet ObjectSheet Object ManualSheet Object API Reference
Prop TypesProp Types ManualProp Types API reference

Usage

This hook must be initialized inside a child component of <Sheet>:

// Scene.svelte
<script lang="ts">
  import { createSheetObjectAction, useSequence } from '@threlte/theatre'

  const sheetObjectAction = createSheetObjectAction()
</script>

<div
	use:sheetObjectAction={{
		key: 'foo',
		props: { width: 230 },
		callback: {node, { width }} => {
			node.style.width = `${width}px`;
		}
	}}
>
	I Am Animated!
</div>

Where the parent component looks something like this:

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

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

// App.svelte
<Project config={{ state }}>
  <Sheet>
    <Sequence />
    <Scene />
  </Sheet>
</Project>

This is because under the hood we must first retrieve the sheet context so we can instantiate the object in it.

Example

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

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

<Studio />

<Project config={{ state }}>
  <Sheet>
    <Sequence />
    <Scene />
  </Sheet>
</Project>
<script lang="ts">
  import { createSheetObjectAction, useSequence } from '@threlte/theatre'

  const sheetObjectAction = createSheetObjectAction()

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

  const toggle = () => ($playing ? pause() : play())
</script>

<div>
  <button
    on:click={toggle}
    use:sheetObjectAction={{
      key: 'button',
      props: { x: 0, y: 0, bold: false },
      callback: (node, { x, y, bold }) => {
        node.style.transform = `translateX(${x}px) translateY(${y}px)`
        node.style.fontWeight = bold ? 'bold' : 'normal'
      }
    }}
  >
    Click Me!
    {$position.toFixed(2)}
  </button>
</div>

<style>
  div {
    height: 100%;
    display: flex;
    place-items: center;
    justify-content: center;
  }

  button {
    background-color: white;
    padding: 0.5rem;
    border-radius: 0.5rem;
    height: fit-content;
  }
</style>
<svg
  xmlns="http://www.w3.org/2000/svg"
  viewBox="0 0 256 256"
>
  <rect
    width="256"
    height="256"
    fill="none"
  />
  <path
    d="M216,48V208a16,16,0,0,1-16,16H160a16,16,0,0,1-16-16V48a16,16,0,0,1,16-16h40A16,16,0,0,1,216,48ZM96,32H56A16,16,0,0,0,40,48V208a16,16,0,0,0,16,16H96a16,16,0,0,0,16-16V48A16,16,0,0,0,96,32Z"
  />
</svg>
<svg
  xmlns="http://www.w3.org/2000/svg"
  viewBox="0 0 256 256"
>
  <rect
    width="256"
    height="256"
    fill="none"
  />
  <path
    d="M240,128a15.74,15.74,0,0,1-7.6,13.51L88.32,229.65a16,16,0,0,1-16.2.3A15.86,15.86,0,0,1,64,216.13V39.87a15.86,15.86,0,0,1,8.12-13.82,16,16,0,0,1,16.2.3L232.4,114.49A15.74,15.74,0,0,1,240,128Z"
  />
</svg>
export { default as PlayIcon } from './PlayIcon.svelte'
export { default as PauseIcon } from './PauseIcon.svelte'
{
  "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": 1,
        "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"
            }
          }
        }
      }
    }
  },
  "definitionVersion": "0.4.0",
  "revisionHistory": ["WdqDOLSNW-TCSoDz", "ZxoPi9jfsYCHwP__"]
}

Action

The action takes the following arguments:

argtypedescription
keystringThe key of the object, shown in the studio UI (may be namespaced with slashes)
propsPropsDeclaration of your props and their types (see Theatre.js manual entry and API reference)
callback(node: HTMLElement, props: Props) => voidA callback function called to update the HTMLElement node whenever the prop changes.