Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

animationFrames should emit the timestamp from requestAnimationFrame's callback #5194

Closed
kirk-l opened this issue Dec 25, 2019 · 0 comments · Fixed by #5438
Closed

animationFrames should emit the timestamp from requestAnimationFrame's callback #5194

kirk-l opened this issue Dec 25, 2019 · 0 comments · Fixed by #5438
Assignees

Comments

@kirk-l
Copy link

kirk-l commented Dec 25, 2019

Bug Report

Opening a bug report, per @cartant here.

Current Behavior
Why doesn't the animationFrames Observable -- added in #5021 -- pass the DOMHighResTimeStamp that the requestAnimationFrame callback receives, to its subscribers? According to MDN:

When callbacks queued by requestAnimationFrame() begin to fire multiple callbacks in a single frame, each receives the same timestamp even though time has passed during the computation of every previous callback's workload.

This is critical when running multiple rAF loops to keep them in sync. The current default implementation, using Date.now(), will emit slightly different values for each loop and to each subscriber.

Reproduction
Comparison of using two Observables with the rAF timestamp, then two uses of Date in animationFrames. The two timestamps always show the same elapsed ms, while the two Dates will (randomly) show different elapsed ms.
https://codepen.io/kirk-l/pen/BayZQyK

Expected behavior
Pass the timestamp from requestAnimationFrame's callback to subscribers.

Environment

  • Runtime: browser
  • RxJS version: 7.0.0-alpha

Possible Solution
Here's the implementation I use:

const animationFrames = new Observable(subscriber => {
    let requestId = window.requestAnimationFrame(function step(timestamp) {
        subscriber.next(timestamp);
        if (!subscriber.closed) {
            requestId = window.requestAnimationFrame(step);
        }
    });
    return () => window.cancelAnimationFrame(requestId);
});

// And to get the elapsed milliseconds:
const elapsedMs = defer(() => {
    let start = null;
    return animationFrames.pipe(
        tap(timestamp => start === null && (start = timestamp)),
        map(timestamp => timestamp - start),
    );
});

I think this would be a better animationFrames Observable.

@kirk-l kirk-l changed the title Pass the timestamp from requestAnimationFrame callback to subscribers animationFrames should emit the timestamp from requestAnimationFrame's callback Dec 25, 2019
@cartant cartant added the AGENDA ITEM Flagged for discussion at core team meetings label Jan 16, 2020
@benlesh benlesh added help wanted Issues we wouldn't mind assistance with. and removed AGENDA ITEM Flagged for discussion at core team meetings help wanted Issues we wouldn't mind assistance with. labels Feb 12, 2020
@benlesh benlesh self-assigned this Feb 12, 2020
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging a pull request may close this issue.

3 participants