Add TSDocs to rafDriver
This commit is contained in:
parent
d649858529
commit
e0465ed3fa
5 changed files with 120 additions and 4 deletions
|
@ -138,6 +138,7 @@ const validateProjectIdOrThrow = (value: string) => {
|
||||||
*
|
*
|
||||||
* @param pointer - A Pointer (like `object.props.x`)
|
* @param pointer - A Pointer (like `object.props.x`)
|
||||||
* @param callback - The callback is called every time the value of pointer changes
|
* @param callback - The callback is called every time the value of pointer changes
|
||||||
|
* @param rafDriver - (optional) The `rafDriver` to use. Learn how to use `rafDriver`s [from the docs](https://www.theatrejs.com/docs/latest/manual/advanced#rafdrivers).
|
||||||
* @returns An unsubscribe function
|
* @returns An unsubscribe function
|
||||||
*
|
*
|
||||||
* @example
|
* @example
|
||||||
|
@ -165,9 +166,9 @@ export function onChange<
|
||||||
? T
|
? T
|
||||||
: unknown,
|
: unknown,
|
||||||
) => void,
|
) => void,
|
||||||
driver?: IRafDriver,
|
rafDriver?: IRafDriver,
|
||||||
): VoidFn {
|
): VoidFn {
|
||||||
const ticker = driver ? privateAPI(driver).ticker : getCoreTicker()
|
const ticker = rafDriver ? privateAPI(rafDriver).ticker : getCoreTicker()
|
||||||
|
|
||||||
if (isPointer(pointer)) {
|
if (isPointer(pointer)) {
|
||||||
const pr = pointerToPrism(pointer)
|
const pr = pointerToPrism(pointer)
|
||||||
|
|
|
@ -3,6 +3,10 @@ import {privateAPI} from './privateAPIs'
|
||||||
import type {IRafDriver, RafDriverPrivateAPI} from './rafDrivers'
|
import type {IRafDriver, RafDriverPrivateAPI} from './rafDrivers'
|
||||||
import {createRafDriver} from './rafDrivers'
|
import {createRafDriver} from './rafDrivers'
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates a rafDrive that uses `window.requestAnimationFrame` in browsers,
|
||||||
|
* or a single `setTimeout` in SSR.
|
||||||
|
*/
|
||||||
function createBasicRafDriver(): IRafDriver {
|
function createBasicRafDriver(): IRafDriver {
|
||||||
let rafId: number | null = null
|
let rafId: number | null = null
|
||||||
const start = (): void => {
|
const start = (): void => {
|
||||||
|
@ -35,6 +39,9 @@ function createBasicRafDriver(): IRafDriver {
|
||||||
|
|
||||||
let coreRafDriver: RafDriverPrivateAPI | undefined
|
let coreRafDriver: RafDriverPrivateAPI | undefined
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the rafDriver that is used by the core internally. Creates a new one if it's not set yet.
|
||||||
|
*/
|
||||||
export function getCoreRafDriver(): RafDriverPrivateAPI {
|
export function getCoreRafDriver(): RafDriverPrivateAPI {
|
||||||
if (!coreRafDriver) {
|
if (!coreRafDriver) {
|
||||||
setCoreRafDriver(createBasicRafDriver())
|
setCoreRafDriver(createBasicRafDriver())
|
||||||
|
@ -42,10 +49,17 @@ export function getCoreRafDriver(): RafDriverPrivateAPI {
|
||||||
return coreRafDriver!
|
return coreRafDriver!
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @returns The ticker that is used by the core internally.
|
||||||
|
*/
|
||||||
export function getCoreTicker(): Ticker {
|
export function getCoreTicker(): Ticker {
|
||||||
return getCoreRafDriver().ticker
|
return getCoreRafDriver().ticker
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets the rafDriver that is used by the core internally.
|
||||||
|
*/
|
||||||
export function setCoreRafDriver(driver: IRafDriver) {
|
export function setCoreRafDriver(driver: IRafDriver) {
|
||||||
if (coreRafDriver) {
|
if (coreRafDriver) {
|
||||||
throw new Error(`\`setCoreRafDriver()\` is already called.`)
|
throw new Error(`\`setCoreRafDriver()\` is already called.`)
|
||||||
|
|
|
@ -6,8 +6,19 @@ export interface IRafDriver {
|
||||||
* All raf derivers have have `driver.type === 'Theatre_RafDriver_PublicAPI'`
|
* All raf derivers have have `driver.type === 'Theatre_RafDriver_PublicAPI'`
|
||||||
*/
|
*/
|
||||||
readonly type: 'Theatre_RafDriver_PublicAPI'
|
readonly type: 'Theatre_RafDriver_PublicAPI'
|
||||||
|
/**
|
||||||
|
* The name of the driver. This is used for debugging purposes.
|
||||||
|
*/
|
||||||
name: string
|
name: string
|
||||||
|
/**
|
||||||
|
* The id of the driver. This is used for debugging purposes.
|
||||||
|
* It's guaranteed to be unique.
|
||||||
|
*/
|
||||||
id: number
|
id: number
|
||||||
|
/**
|
||||||
|
* This is called by the driver when it's time to tick forward.
|
||||||
|
* The time param is of the same type returned by `performance.now()`.
|
||||||
|
*/
|
||||||
tick: (time: number) => void
|
tick: (time: number) => void
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -21,6 +32,95 @@ export interface RafDriverPrivateAPI {
|
||||||
|
|
||||||
let lastDriverId = 0
|
let lastDriverId = 0
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates a custom raf driver.
|
||||||
|
* `rafDriver`s allow you to control when and how often computations in Theatre tick forward. (raf stands for [`requestAnimationFrame`](https://developer.mozilla.org/en-US/docs/Web/API/window/requestAnimationFrame)).
|
||||||
|
* The default `rafDriver` in Theatre creates a `raf` loop and ticks forward on each frame. You can create your own `rafDriver`, which enables the following use-cases:
|
||||||
|
*
|
||||||
|
* 1. When using Theatre.js alongside other animation libs (`@react-three/fiber`/`gsap`/`lenis`/`etc`), you'd want all animation libs to use a single `raf` loop to keep the libraries in sync and also to get better performance.
|
||||||
|
* 2. In XR sessions, you'd want Theatre to tick forward using [`xr.requestAnimationFrame()`](https://developer.mozilla.org/en-US/docs/Web/API/XRSession/requestAnimationFrame).
|
||||||
|
* 3. In some advanced cases, you'd just want to manually tick forward (many ticks per frame, or skipping many frames, etc). This is useful for recording an animation, rendering to a file, testing an animation, running benchmarks, etc.
|
||||||
|
*
|
||||||
|
* Here is how you'd create a custom `rafDriver`:
|
||||||
|
*
|
||||||
|
* ```js
|
||||||
|
* import { createRafDriver } from '@theatre/core'
|
||||||
|
*
|
||||||
|
* const rafDriver = createRafDriver({ name: 'a custom 5fps raf driver' })
|
||||||
|
*
|
||||||
|
* setInterval(() => {
|
||||||
|
* rafDriver.tick(performance.now())
|
||||||
|
* }, 200)
|
||||||
|
* ```
|
||||||
|
*
|
||||||
|
* Now, any time you set up an `onChange()` listener, pass your custom `rafDriver`:
|
||||||
|
*
|
||||||
|
* ```js
|
||||||
|
* import { onChange } from '@theatre/core'
|
||||||
|
*
|
||||||
|
* onChange(
|
||||||
|
* // let's say object is a Theatre object, the one returned from calling `sheet.object()`
|
||||||
|
* object.props,
|
||||||
|
* // this callback will now only be called at 5fps (and won't be called if there are no new values)
|
||||||
|
* // even if `sequence.play()` updates `object.props` at 60fps, this listener is called a maximum of 5fps
|
||||||
|
* (propValues) => {
|
||||||
|
* console.log(propValues)
|
||||||
|
* },
|
||||||
|
* rafDriver,
|
||||||
|
* )
|
||||||
|
*
|
||||||
|
* // this will update the values of `object.props` at 60fps, but the listener above will still get called a maximum of 5fps
|
||||||
|
* sheet.sequence.play()
|
||||||
|
*
|
||||||
|
* // we can also customize at what resolution the sequence's playhead moves forward
|
||||||
|
* sheet.sequence.play({ rafDriver }) // the playhead will move forward at 5fps
|
||||||
|
* ```
|
||||||
|
*
|
||||||
|
* You can optionally make studio use this `rafDriver`. This means the parts of the studio that tick based on raf, will now tick at 5fps. This is only useful if you're doing something crazy like running the studio (and not the core) in an XR frame.
|
||||||
|
*
|
||||||
|
* ```js
|
||||||
|
* studio.initialize({
|
||||||
|
* __experimental_rafDriver: rafDriver,
|
||||||
|
* })
|
||||||
|
* ```
|
||||||
|
*
|
||||||
|
* `rafDriver`s can optionally provide a `start/stop` callback. Theatre will call `start()` when it actually has computations scheduled, and will call `stop` if there is nothing to update after a few ticks:
|
||||||
|
*
|
||||||
|
* ```js
|
||||||
|
* import { createRafDriver } from '@theatre/core'
|
||||||
|
* import type { IRafDriver } from '@theare/core'
|
||||||
|
*
|
||||||
|
* function createBasicRafDriver(): IRafDriver {
|
||||||
|
* let rafId: number | null = null
|
||||||
|
* const start = (): void => {
|
||||||
|
* if (typeof window !== 'undefined') {
|
||||||
|
* const onAnimationFrame = (t: number) => {
|
||||||
|
* driver.tick(t)
|
||||||
|
* rafId = window.requestAnimationFrame(onAnimationFrame)
|
||||||
|
* }
|
||||||
|
* rafId = window.requestAnimationFrame(onAnimationFrame)
|
||||||
|
* } else {
|
||||||
|
* driver.tick(0)
|
||||||
|
* setTimeout(() => driver.tick(1), 0)
|
||||||
|
* }
|
||||||
|
* }
|
||||||
|
*
|
||||||
|
* const stop = (): void => {
|
||||||
|
* if (typeof window !== 'undefined') {
|
||||||
|
* if (rafId !== null) {
|
||||||
|
* window.cancelAnimationFrame(rafId)
|
||||||
|
* }
|
||||||
|
* } else {
|
||||||
|
* // nothing to do in SSR
|
||||||
|
* }
|
||||||
|
* }
|
||||||
|
*
|
||||||
|
* const driver = createRafDriver({ name: 'DefaultCoreRafDriver', start, stop })
|
||||||
|
*
|
||||||
|
* return driver
|
||||||
|
* }
|
||||||
|
* ```
|
||||||
|
*/
|
||||||
export function createRafDriver(conf?: {
|
export function createRafDriver(conf?: {
|
||||||
name?: string
|
name?: string
|
||||||
start?: () => void
|
start?: () => void
|
||||||
|
|
|
@ -79,8 +79,9 @@ export interface ISequence {
|
||||||
direction?: IPlaybackDirection
|
direction?: IPlaybackDirection
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Optionally provide a RAF driver to use for the playback. It'll default to
|
* Optionally provide a rafDriver to use for the playback. It'll default to
|
||||||
* the core driver if not provided, which is a `requestAnimationFrame()` driver.
|
* the core driver if not provided, which is a `requestAnimationFrame()` driver.
|
||||||
|
* Learn how to use `rafDriver`s [from the docs](https://www.theatrejs.com/docs/latest/manual/advanced#rafdrivers).
|
||||||
*/
|
*/
|
||||||
rafDriver?: IRafDriver
|
rafDriver?: IRafDriver
|
||||||
}): Promise<boolean>
|
}): Promise<boolean>
|
||||||
|
|
|
@ -72,7 +72,7 @@ export interface ISheetObject<
|
||||||
* Calls `fn` every time the value of the props change.
|
* Calls `fn` every time the value of the props change.
|
||||||
*
|
*
|
||||||
* @param fn - The callback is called every time the value of the props change, plus once at the beginning.
|
* @param fn - The callback is called every time the value of the props change, plus once at the beginning.
|
||||||
* @param rafDriver - (Optional) The RAF driver to use. Defaults to the core RAF driver.
|
* @param rafDriver - (optional) The `rafDriver` to use. Learn how to use `rafDriver`s [from the docs](https://www.theatrejs.com/docs/latest/manual/advanced#rafdrivers).
|
||||||
* @returns an Unsubscribe function
|
* @returns an Unsubscribe function
|
||||||
*
|
*
|
||||||
* @example
|
* @example
|
||||||
|
|
Loading…
Reference in a new issue