Skip to content

Instantly share code, notes, and snippets.

@unicornware
Created January 3, 2022 07:40
Show Gist options
  • Select an option

  • Save unicornware/6fbd2541474c2274c1beceb94627b5d9 to your computer and use it in GitHub Desktop.

Select an option

Save unicornware/6fbd2541474c2274c1beceb94627b5d9 to your computer and use it in GitHub Desktop.
usePixiTicker
/**
* @file Hook Entry Point - usePixiTicker
* @module ui/hooks/usePixiTicker
*/
export { default as usePixiTicker } from './use-pixi-ticker'
export * from './use-pixi-ticker.types'
import type { OrUndefined } from '@flex-development/tutils'
import isNIL from '@flex-development/tutils/guards/is-nil.guard'
import { Ticker } from '@packages/ui/pixi'
import { getFluidValue } from '@react-spring/shared'
import noop from '@stdlib/utils-noop'
import { useCallback, useEffect, useState } from 'react'
import type { CurrentTime as Time } from './use-pixi-ticker.types'
import {
UsePixiTicker as HookResult,
UsePixiTickerOnStart as OnStart,
UsePixiTickerOnStop as OnStop,
UsePixiTickerOnUpdate as OnUpdate,
UsePixiTickerOptions as Options
} from './use-pixi-ticker.types'
/**
* @file Hooks - usePixiTicker
* @module ui/hooks/usePixiTicker
*/
/**
* Creates a [PIXI][1] {@link Ticker} instance.
*
* [1]: https://pixijs.download/dev/docs/index.html
* [2]: https://pixijs.download/dev/docs/PIXI.Ticker.html#start
* [3]: https://pixijs.download/dev/docs/PIXI.Ticker.html#update
* [4]: https://pixijs.download/dev/docs/PIXI.Ticker.html#stop
* [5]: https://pixijs.download/dev/docs/PIXI.Ticker.html#deltaTime
*
* @see https://pixijs.download/release/docs/PIXI.Ticker.html
*
* @param {Options} [options=DEFAULT_OPTIONS] - Ticker options
* @param {boolean} [options.autoStart=true] - [Start][2] ticker automatically
* @param {Time} [options.initialTime=Number.NaN] - Initial ticker duration (ms)
* @param {number} [options.maxFPS=0] - Minimum amount of milliseconds required
* to elapse between invoking [`PIXI.Ticker#update`][3]
* @param {number} [options.minFPS=0] - Maximum amount of milliseconds allowed
* to elapse between invoking [`PIXI.Ticker#update`][3]
* @param {OnStart} [options.onStart=noop] - Fires when ticker is [started][2]
* @param {OnStop} [options.onStop=noop] - Fires when ticker is [stopped][4]
* @param {OnUpdate} [options.onUpdate=noop] - Fires when [update][3] is called
* @param {number} [options.speed=1] - Factor of current [`deltaTime`][5]
* @return {HookResult} New {@link Ticker} instance
*/
function usePixiTicker({
autoStart = DEFAULT_OPTIONS.autoStart,
initialTime = DEFAULT_OPTIONS.initialTime,
maxFPS = DEFAULT_OPTIONS.maxFPS,
minFPS = DEFAULT_OPTIONS.minFPS,
onStart = DEFAULT_OPTIONS.onStart,
onStop = DEFAULT_OPTIONS.onStop,
onUpdate = DEFAULT_OPTIONS.onUpdate,
speed = DEFAULT_OPTIONS.speed
}: Options = DEFAULT_OPTIONS): HookResult {
// Init Ticker state
const [ticker] = useState<Ticker>(new Ticker())
/** Callback version {@link onStart} */
const onStartCB = useCallback(onStart, [onStart])
/** Callback version {@link onStop} */
const onStopCB = useCallback(onStop, [onStop])
/** Callback version {@link onUpdate} */
const onUpdateCB = useCallback(onUpdate, [onUpdate])
/**
* Starts the ticker. If the ticker has listeners a new animation frame is
* requested at this point.
*
* @see https://pixijs.download/dev/docs/PIXI.Ticker.html#start
*
* @return {void} Nothing when complete
*/
const start = (): void => {
ticker.start()
return onStartCB(ticker)
}
/** Callback version {@link start} */
const startCB = useCallback(start, [start])
/**
* Stops the ticker. If the ticker has requested an animation frame it is
* canceled at this point.
*
* @see https://pixijs.download/dev/docs/PIXI.Ticker.html#stop
*
* @return {void} Nothing when complete
*/
const stop = (): void => {
ticker.stop()
return onStopCB(ticker)
}
/** Callback version {@link stop} */
const stopCB = useCallback(stop, [stop])
/**
* Triggers an update.
*
* An update entails setting the current [`PIXI.Ticker#elapsedMS`][1], the
* current [`PIXI.Ticker#deltaTime`][2], invoking all listeners with current
* `deltaTime`, and then finally setting [`PIXI.Ticker#lastTime`][3] with the
* value of {@link currentTime} that was provided.
*
* This function will be called automatically by animation frame callbacks if
* the ticker instance has been started and listeners are added.
*
* [1]: https://pixijs.download/dev/docs/PIXI.Ticker.html#elapsedMS
* [2]: https://pixijs.download/dev/docs/PIXI.Ticker.html#deltaTime
* [3]: https://pixijs.download/dev/docs/PIXI.Ticker.html#lastTime
*
* @param {Time} [currentTime=performance.now()] - Execution time
* @return {void} Nothing when complete
*/
const update = (currentTime: Time = performance.now()): void => {
onUpdateCB(currentTime, ticker)
let current = isNIL(currentTime) ? undefined : getFluidValue(currentTime)
if (Number.isNaN(current)) current = undefined
return ticker.update(current as OrUndefined<number>)
}
/** Callback version of {@link update} */
const updateCB = useCallback(update, [onUpdateCB, ticker, update])
// Set ticker#autoStart
/** @see https://pixijs.download/dev/docs/PIXI.Ticker.html#autoStart */
useEffect(() => {
ticker.autoStart = autoStart
}, [autoStart, ticker])
// Set ticker#maxFPS
/** @see https://pixijs.download/dev/docs/PIXI.Ticker.html#maxFPS */
useEffect(() => {
if (typeof maxFPS === 'number' && !Number.isNaN(maxFPS)) {
ticker.maxFPS = maxFPS
}
}, [maxFPS, ticker])
// Set ticker#minFPS
/** @see https://pixijs.download/dev/docs/PIXI.Ticker.html#minFPS */
useEffect(() => {
if (typeof minFPS === 'number' && !Number.isNaN(minFPS)) {
ticker.minFPS = minFPS
}
}, [minFPS, ticker])
// Set ticker#speed
/** @see https://pixijs.download/dev/docs/PIXI.Ticker.html#speed */
useEffect(() => {
if (typeof speed === 'number' && !Number.isNaN(speed)) ticker.speed = speed
}, [speed, ticker])
// Set initial ticker duration
useEffect(() => {
updateCB(initialTime)
}, [initialTime, updateCB])
return { start: startCB, stop: stopCB, ticker, update: updateCB }
}
const DEFAULT_OPTIONS: Required<Options> = {
autoStart: false,
initialTime: Number.NaN,
maxFPS: 0,
minFPS: 10,
onStart: noop,
onStop: noop,
onUpdate: noop,
speed: 1
}
usePixiTicker.DEFAULT_OPTIONS = DEFAULT_OPTIONS
export default usePixiTicker
import type { OrUndefined } from '@flex-development/tutils'
import type { Ticker } from '@packages/ui/pixi'
import type { FluidValue } from '@react-spring/shared'
/**
* @file Type Definitions - usePixiTicker
* @module ui/hooks/types/usePixiTicker
*/
export type UsePixiTicker = {
start: Ticker['start']
stop: Ticker['stop']
ticker: Ticker
update(currentTime?: CurrentTime): void
}
export type UsePixiTickerOptions = {
/**
* [Start][1] ticker automatically when a listener is added.
*
* The function will be memoized with [`useCallback`][2].
*
* [1]: https://pixijs.download/dev/docs/PIXI.Ticker.html#start
* [2]: https://reactjs.org/docs/hooks-reference.html#usecallback
*
* @default false
*/
autoStart?: Ticker['autoStart']
/**
* Initial ticker duration in milliseconds.
*
* @default Number.NaN
*/
initialTime?: CurrentTime
/**
* Minimum amount of milliseconds required to elapse between invoking
* [`PIXI.Ticker#update`][1].
*
* This will effect the measured value of [`PIXI.Ticker#FPS`][2].
*
* If it is set to `0`, then there is no limit; PixiJS will render as many
* frames as it can. Otherwise it will be at least [`minFPS`][3].
*
* [1]: https://pixijs.download/dev/docs/PIXI.Ticker.html#update
* [2]: https://pixijs.download/dev/docs/PIXI.Ticker.html#FPS
* [3]: https://pixijs.download/dev/docs/PIXI.Ticker.html#minFPS
*
* @default 0
*/
maxFPS?: number
/**
* Maximum amount of milliseconds allowed to elapse between invoking
* [`PIXI.Ticker#update`][1].
*
* This value is used to cap [`PIXI.Ticker#deltaTime`][2], but does not effect
* the measured value of [`PIXI.Ticker#FPS`][3].
*
* When setting this property it is clamped to a value between `0` and
* `settings.TARGET_FPMS * 1000`.
*
* [1]: https://pixijs.download/dev/docs/PIXI.Ticker.html#update
* [2]: https://pixijs.download/dev/docs/PIXI.Ticker.html#deltaTime
* [3]: https://pixijs.download/dev/docs/PIXI.Ticker.html#FPS
*
* @default 10
*/
minFPS?: number
/**
* Callback to fire when ticker is started.
*
* The function will be memoized with [`useCallback`][1].
*
* [1]: https://reactjs.org/docs/hooks-reference.html#usecallback
*
* @default noop
*/
onStart?: UsePixiTickerOnStart
/**
* Callback to fire when ticker is stopped.
*
* The function will be memoized with [`useCallback`][1].
*
* [1]: https://reactjs.org/docs/hooks-reference.html#usecallback
*
* @default noop
*/
onStop?: UsePixiTickerOnStop
/**
* Callback to fire when ticker duration is updated.
*
* The function will be memoized with [`useCallback`][1].
*
* [1]: https://reactjs.org/docs/hooks-reference.html#usecallback
*
* @default noop
*/
onUpdate?: UsePixiTickerOnUpdate
/**
* Factor of current [`deltaTime`][1].
*
* [1]: https://pixijs.download/dev/docs/PIXI.Ticker.html#deltaTime
*
* @default 1
*/
speed?: Ticker['speed']
}
/**
* Current execution time.
*
* @see https://pixijs.download/dev/docs/PIXI.Ticker.html#update
*/
export type CurrentTime = number | FluidValue<number>
/**
* Callback to fire when ticker is started.
*
* @param {Ticker} ticker - Current {@link Ticker} instance
* @return {void} Nothing when complete
*/
export type UsePixiTickerOnStart = (ticker: Ticker) => void
/**
* Callback to fire when ticker is stopped.
*
* @param {Ticker} ticker - Current {@link Ticker} instance
* @return {void} Nothing when complete
*/
export type UsePixiTickerOnStop = (ticker: Ticker) => void
/**
* Callback to fire when ticker is updated.
*
* @param {OrUndefined<CurrentTime>} currentTime - Current execution time
* @param {Ticker} ticker - Current {@link Ticker} instance
* @return {void} Nothing when complete
*/
export type UsePixiTickerOnUpdate = (
currentTime: OrUndefined<CurrentTime>,
ticker: Ticker
) => void
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment