@theatre/core
getProject(id, config)
If you import and initialize Studio, you can call getProject()
without an explicit state.
In this case, the state of the project will be managed by Studio.
import { getProject } from '@theatre/core'const config = {} // the config can be empty when starting a new projectconst project = getProject('My Project', config)
In production, however, you'd pass a state object, which is exported from Studio in the config argument.
import { getProject } from '@theatre/core'import state from './saved-state.json'const config = { state } // here the config contains our saved stateconst project = getProject('My Project', config)
Project
Project returned by getProject
.
To read about Projects, check out the Projects Manual!
project.ready
Promise
that resolves when Theatre.js is loaded. If @theatre/studio
is used, this Promise
would resolve when Studio has loaded the state of the project into memory. If @theatre/studio
is not used, this Promise
is already resolved.
project.ready.then(() => console.log('Project loaded!'))
project.isReady
Indicates whether the project is ready to be used.
It is better to use Project.ready, which is a Promise
that resolves when the project is ready.
if (project.isReady) { console.log('Project loaded!')} else { console.log('Project not loaded yet.')}
project.address
The Project's unique address in Theatre.js.
It is a JS object that contains a single property projectId
.
const { projectId } = project.address
project.sheet(name, instanceId?)
Creates or returns a Sheet under the Project. If a Sheet with the given name is in the Project's state then the existing Sheet is returned; otherwise, a new Sheet is created and returned. You can optionally give a second argument: a sheet instance id that allows you to create multiple instances of the same Sheet (this makes it possible to have multiple instances of the same animation). By default, the instance id is the same as the Sheet id.
import { getProject } from '@theatre/core'const project = getProject('My Project')const sheet = project.sheet('My Sheet', 'My optional Sheet instance id')
project.getAssetUrl(assetHandle)Since 0.6.0
Gets the url for the provided asset handle. You would normally get an asset handle by listening to changes of asset props, like the image prop.
const object = sheet.object('My Object', { texture: types.image(undefined, { label: 'Texture', }),})object.onValuesChange(({ texture }) => { setImageUrl(project.getAssetUrl(texture))})
Sheet
Sheet returned by Project.sheet
.
sheet.object(key, config, options?)
Creates or returns an Object with given props under this Sheet. If an Object with the given name is in the Project's state then the existing Object is returned; otherwise, a new Object is created and returned.
// Create an object with nested propsconst myObject = sheet.object('My Object', { position: { x: 0, y: 0 } })// {x: 0, y: 0}console.log(myObject.value.position)
Objects can also be reconfigured on the fly. Learn more here.
sheet.detachObject(key)Since 0.5.1
Detaches a previously created child object from the sheet.
If you call sheet.object(key)
again with the same key
, the values of the object's props WILL NOT be reset to their initial values.
Note: Calling sheet.detachObject()
does not unsubscribe the listeners you've attached to the object. For
example, if you've called const unsubscribe = object.onValuesChange(...)
, you
will have to manually call unsubscribe()
either before or after calling sheet.detachObject()
.
sheet.sequence
The Sequence of this sheet. Sequences are JS objects that hold animation data such as Keyframes and current position.
sheet.project
The Project this Sheet belongs to.
import { getProject } from '@theatre/core'const project = getProject('My Project')const sheet = project.sheet('My Sheet')// trueconsole.log(sheet.project === project)
sheet.address
The Sheet's unique address in Theatre.js.
It is an object containing a projectId
, sheetId
, and sheetInstanceId
.
import { getProject } from '@theatre/core'const project = getProject('My Project')const sheet = project.sheet('My Sheet')const { projectId, sheetId, sheetInstanceId } = sheet.address
Sequence
A JS object that holds animation data such as Keyframes and current position.
sequence.play(opts?)
Starts playback of a sequence. Returns a Promise
that either resolves to true
when the playback completes or resolves
to false
if playback gets interrupted (for example by calling Sequence.pause
)
// plays the sequence from the current position to sequence.lengthsheet.sequence.play()// plays the sequence at 2.4x speedsheet.sequence.play({ rate: 2.4 })// plays the sequence from second 1 to 4sheet.sequence.play({ range: [1, 4] })// plays the sequence 4 timessheet.sequence.play({ iterationCount: 4 })// plays the sequence in reversesheet.sequence.play({ direction: 'reverse' })// plays the sequence back and forth forever (until interrupted)sheet.sequence.play({ iterationCount: Infinity, direction: 'alternateReverse' })// plays the sequence and logs "done" once playback is finishedsheet.sequence.play().then(() => console.log('done'))// play the sequence using the given rafDriver (since version 0.6.0)sheet.sequence.play({ rafDriver })
Hint: You can control how often sequence.play()
progresses forward by optionally providing a rafDriver
.
sequence.pause()
Pauses the currently playing animation.
sheet.sequence.play()setTimeout(() => sheet.sequence.pause(), 1000) // pause after 1 second
sequence.position
The current position of the playhead. In a time-based sequence, this represents the current time in seconds.
// if the animation is past the 1 second markif (sheet.sequence.position > 1) { // do something}
// set the animation position to 1 secondsheet.sequence.position = 1
sequence.pointer
A Pointer to the Sequence's inner state.
As with any Pointer, you can use this with onChange()
to listen to its value changes or with val()
to read its current value.
import { onChange, val } from '@theatre/core'// ...onChange(sequence.pointer.length, (len) => { console.log('Length of the sequence changed to:', len)})onChange(sequence.pointer.position, (position) => { console.log('Position of the sequence changed to:', position)})onChange(sequence.pointer.playing, (playing) => { console.log(playing ? 'playing' : 'paused')})// we can also read the current value of the pointerconsole.log('current length is', val(sequence.pointer.length))
sequence.attachAudio(opts)
Attaches an audio source to the sequence. Playing the sequence automatically plays the audio source and the audio and animation times are kept in sync.
Returns a Promise
that resolves once the audio source is loaded and decoded.
Learn more from the Using Audio manual.
// Loads and decodes audio from the URL and then attaches it to the sequenceawait sheet.sequence.attachAudio({source: "http://localhost:3000/audio.mp3"})sheet.sequence.play()// Providing your own AudioAPI Context, destination, etcconst audioContext: AudioContext = {...} // create an AudioContext using the Audio APIconst audioBuffer: AudioBuffer = {...} // create an AudioBufferconst destinationNode = audioContext.destinationawait sheet.sequence.attachAudio({source: audioBuffer, audioContext, destinationNode})
Note: It's better to provide the audioContext
rather than allow Theatre.js to create it. That's because some browsers
suspend the audioContext
unless it's initiated by a user
gesture, like a click. If that happens, Theatre.js will wait for a user gesture to resume the audioContext
. But that's
probably not an optimal user experience. It is better to provide a button or some other UI element to communicate to
the user that they have to initiate the animation.
// html: <button id="#start">start</button>const button = document.getElementById('start')button.addEventListener('click', async () => { const audioContext = somehowCreateAudioContext() await sheet.sequence.attachAudio({ audioContext, source: '...' }) sheet.sequence.play()})
To read about Audio, check out the Using Audio Manual!
sequence.__experimental_getKeyframes(pointer)Since 0.6.1
Returns the keyframes of a given prop of an object.
const obj = sheet.object('My Object', { position: { x: 0, y: 0 } })// (assuming the user has sequenced the x prop)const keyframes = sequence.__experimental_getKeyframes(obj.props.position.x) // an array of keyframes
Object
A Sheet Object returned by sheet.object
with some given props.
const obj = sheet.object('My Object', { x: 0 })
To read about Objects, check out the Objects Manual.
To read about the props of Objects, check out the Prop Types Manual or the Prop types API docs below!
object.value
The current values of the props of the Object.
const obj = sheet.object('obj', { x: 0 })console.log(obj.value.x) // prints 0 or the current numeric value
object.props
A Pointer to the props of the Object.
onChange(obj.props.x, (x) => { console.log(x)})// we can also read the current value of the pointerconsole.log('current x is', val(obj.props.x))
object.sheet
The instance of Sheet that the Object belongs to.
const sheet = project.sheet('My Sheet')const obj = sheet.object('obj', { x: 0 })// trueconsole.log(obj.sheet === sheet)
object.project
The Project this object belongs to.
const project = getProject('My Project')const sheet = project.sheet('My Sheet')const obj = sheet.object('My Object', { x: 0 })// trueconsole.log(obj.project === project)
object.address
An Object address is a JS object representing the unique address of the Object in Theatre.js.
It contains a projectId
, sheetId
, sheetInstanceId
, and objectKey
.
const { projectId, sheetId, sheetInstanceId, objectKey } = obj.address
object.initialValue
Sets the initial value of the Object. This value overrides the default values defined in the Object's prop types. And, it can then be overridden if the user overrides it in the Studio UI with a static or sequenced value.
const obj = sheet.object('obj', { position: { x: 0, y: 0 } })obj.value // {position: {x: 0, y: 0}}// here, we only override position.xobj.initialValue = { position: { x: 2 } }obj.value // {position: {x: 2, y: 0}}
object.onValuesChange(callback)
Calls a given callback every time any of the Object's prop values change.
Returns an unsubscribe function that can be called to stop listening.
const obj = sheet.object('Box', { position: { x: 0, y: 0 } })const div = document.getElementById('box')const unsubscribe = obj.onValuesChange((newValues) => { div.style.left = newValues.position.x + 'px' div.style.top = newValues.position.y + 'px'})// you can call unsubscribe() to stop listening to changes
Prop types
You can define the types of props when creating an Object through sheet.object
using the types
object.
import { types } from '@theatre/core'
Many prop types allow you to omit the type, and the type is inferred from the initial prop values you provide.
For example, in the following code snippet, the "My Object" Object has a single prop x
with an inferred prop type types.number
.
// A simple number propconst obj = sheet.object('My Object', { x: 0 })
In cases where you want more control over your Object's props, you can specify the type explicitly. Prop types accept options that alter the way the prop behaves when sequenced or displayed in the Studio UI.
// A number prop with custom UIconst obj = sheet.object('My Object', { x: types.number(0, { // limited to 0 and 10 range: [0, 10], }),})
For stringLiteral
, string
, and boolean
types, we can define a custom interpolator as an option, see the code
below for an example.
/** * A string interpolator for a "typewriter effect" when `left` is an empty * string or `right` starts with `left`. */const typeWriterInterpolate = (left: string, right: string, progression: number) => { if (!left || right.startsWith(left)) { const length = Math.floor(Math.max(0, (right.length - left.length) * progression)) return left + right.slice(left.length, left.length + length) } return left}const obj = sheet.object('My Object', { title: types.string('', { interpolate: typeWriterInterpolate }),})
To read about Prop types, check out the Prop Types Manual!
types.compound(props, opts?)
Compound props are analogous to JavaScript objects in that they enable the nesting of props.
In the example below, position
has an inferred prop type of types.compound
.
const obj = sheet.object('My Object', { position: { x: 0, y: 0, },})assert(obj.value.position.x === 0)
You can pass additional options when specifying compound types explicitly.
const obj = sheet.object('My Object', { position: types.compound( { x: 0, y: 0 }, // a custom label for the prop: { label: 'Position' }, ),})
types.number(default, opts?)
A number prop type.
const x = types.number(0, { // The range allowed in the UI (just a visual guide, not a validation rule) range: [0, 10], // Factor influencing the mouse-sensitivity when scrubbing the input nudgeMultiplier: 0.1,})// Number prop with a custom nudging functionconst y = types.number({ nudgeFn: ( // The mouse movement (in pixels) deltaX: number, // The movement as a fraction of the width of the number editor's input deltaFraction: number, // A multiplier that's usually 1, but might be another number if user wants to nudge slower/faster magnitude: number, // The configuration of the number config: { nudgeMultiplier?: number; range?: [number, number] }, ): number => { return deltaX * magnitude },})
types.rgba(default?)
An RGBA prop type. All color channels are normalized between 0 and 1.
// redconst color = types.rgba({ r: 1, g: 0, b: 0, a: 1 })
types.boolean(default)
A boolean prop type. This prop type may take a custom interpolator as an option.
const isOn = types.boolean(true)
types.string(default, opts?)
A string prop type. This prop type may take a custom interpolator as an option.
const message = types.string('Animation Loading')
types.stringLiteral(default, choices, opts?)
A stringLiteral prop type, useful for building menus or radio buttons. This prop type may take a custom interpolator as an option.
String literals can be presented as radio buttons.
const light = types.stringLiteral('r', { r: 'Red', g: 'Green' }, { as: 'switch', label: 'Street Light' })
Or as menus.
const light = types.stringLiteral('r', { r: 'Red', g: 'Green' }, { as: 'menu', label: 'Street Light' })
types.image(default, opts?)Since 0.6.0
An image prop type. This prop type may take a custom interpolator as an option.
Image props are asset props, meaning their values are asset handles that can be used to retrieve a URL for that asset.
The default value for image props is the id of the default asset. If you don't know the id, an empty string or undefined
represents the lack of an assigned asset.
const texture = types.image('', { label: 'Texture',})
types.file(default, opts?)Since 0.7.0
An file prop type. This prop type may take a custom interpolator as an option.
File props are asset props, meaning their values are asset handles that can be used to retrieve a URL for that asset.
The default value for file props is the id of the default asset. If you don't know the id, an empty string or undefined
represents the lack of an assigned asset.
const model = types.file('', { label: '3D Model (GLTF)',})
Pointers
Pointers basically point to values that you can read, observe, and in some cases change.
onChange(pointer, callback, rafDriver?)
Takes a Pointer as the first argument and a callback as the second argument.
Calls the callback every time the value pointed to by pointer
changes.
Returns an unsubscribe function.
import { getProject, onChange } from '@theatre/core'const obj = getProject('A project') .sheet('Scene') .object('Box', { position: { x: 0 } })const usubscribe = onChange(obj.props.position.x, (x) => { console.log('position.x changed to:', x)})setTimeout(usubscribe, 10000) // stop listening to changes after 10 seconds
Hint: You can control how often onChange()
calls the callback by optoinally providing a rafDriver
.
val(pointer)
Takes a Pointer and returns the value it points to.
import { val, getProject } from '@theatre/core'const obj = getProject('A project') .sheet('Scene') .object('Box', { position: { x: 0 } })console.log(val(obj.props.position.x)) // logs the value of obj.props.x
Was this article helpful to you?
Last edited on February 01, 2024.
Edit this page