Skip to content

Commit

Permalink
fix: use rAF time instead of performance.now
Browse files Browse the repository at this point in the history
  • Loading branch information
verekia committed Oct 6, 2024
1 parent 9e52cec commit 46a330b
Show file tree
Hide file tree
Showing 2 changed files with 16 additions and 15 deletions.
6 changes: 3 additions & 3 deletions examples/react/src/App.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -106,7 +106,7 @@ const UI = ({
scrollYRef: RefObject<HTMLDivElement>
}) => {
const mainLoopRef = useRef<HTMLSpanElement>(null)
const MainLoopThrottledRef = useRef<HTMLSpanElement>(null)
const mainLoopThrottledRef = useRef<HTMLSpanElement>(null)
const [joystickMode, setJoystickMode] = useState<'follow' | 'origin'>('follow')

const [count, setCount] = useState(0)
Expand All @@ -125,7 +125,7 @@ const UI = ({

useMainLoop(
({ elapsed, callbackCount }) => {
MainLoopThrottledRef.current!.textContent = `${String(Math.round(elapsed * 1000))} - Counter: ${count} - CBs: ${callbackCount}`
mainLoopThrottledRef.current!.textContent = `${String(Math.round(elapsed * 1000))} - Counter: ${count} - CBs: ${callbackCount}`
},
{ throttle: 100 },
)
Expand Down Expand Up @@ -299,7 +299,7 @@ const UI = ({
useMainLoop: <span className="tabular-nums" ref={mainLoopRef} />
</div>
<div>
useMainLoop (throttled): <span className="tabular-nums" ref={MainLoopThrottledRef} />
useMainLoop (throt.): <span className="tabular-nums" ref={mainLoopThrottledRef} />
</div>
</section>
<section>
Expand Down
25 changes: 13 additions & 12 deletions packages/core/src/main-loop.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,24 +12,31 @@ export type MainLoopEffectOptions = {

type StageNumber = number

type State = {
time: number
delta: number
elapsed: number
callbackCount: number
}

const callbacks = new Map<StageNumber, Set<MainLoopEffectCallback>>()
const callbackLastExecutions = new WeakMap<MainLoopEffectCallback, number>()
const state = { time: 0, delta: 0, elapsed: 0, callbackCount: 0 }
const state: State = { time: 0, delta: 0, elapsed: 0, callbackCount: 0 }
let previousTime = performance.now()
let running = false
let animationFrameId: number | null = null

const mainLoop = (time: number) => {
if (!running) return

state.time = time

let callbackCount = 0
for (const callbacksSet of callbacks.values()) {
callbackCount += callbacksSet.size
}
state.callbackCount = callbackCount

state.time = time

Array.from(callbacks.keys())
.sort((a, b) => a - b)
.forEach(stage => {
Expand All @@ -50,18 +57,12 @@ export const addMainLoopEffect = (
callback: MainLoopEffectCallback,
options?: MainLoopEffectOptions,
) => {
const throttledCallback = (state: {
time: number
delta: number
elapsed: number
callbackCount: number
}) => {
const now = performance.now()
const throttledCallback = (state: State) => {
const lastExecution = callbackLastExecutions.get(callback) || 0
const throttleInterval = options?.throttle || 0

if (now - lastExecution >= throttleInterval) {
callbackLastExecutions.set(callback, now)
if (state.time - lastExecution >= throttleInterval) {
callbackLastExecutions.set(callback, state.time)
state.delta = (state.time - previousTime) / 1000
state.elapsed += state.delta
callback(state)
Expand Down

0 comments on commit 46a330b

Please sign in to comment.