@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 Object | Sheet Object Manual | Sheet Object API Reference |
Prop Types | Prop Types Manual | Prop 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:
arg | type | description |
---|---|---|
key | string | The key of the object, shown in the studio UI (may be namespaced with slashes) |
props | Props | Declaration of your props and their types (see Theatre.js manual entry and API reference) |
callback | (node: HTMLElement, props: Props) => void | A callback function called to update the HTMLElement node whenever the prop changes. |