d358070e91f73d9bfcbe269f39e94e224492c52af9dda10d7bb8ca84fc203e2002aab7a4c1c901ee6fbf12bfe60543dfebccedceaa4cf8c638c17dd7ea5523 1.6 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344
  1. import { Subscription } from '../Subscription';
  2. interface AnimationFrameProvider {
  3. schedule(callback: FrameRequestCallback): Subscription;
  4. requestAnimationFrame: typeof requestAnimationFrame;
  5. cancelAnimationFrame: typeof cancelAnimationFrame;
  6. delegate:
  7. | {
  8. requestAnimationFrame: typeof requestAnimationFrame;
  9. cancelAnimationFrame: typeof cancelAnimationFrame;
  10. }
  11. | undefined;
  12. }
  13. export const animationFrameProvider: AnimationFrameProvider = {
  14. // When accessing the delegate, use the variable rather than `this` so that
  15. // the functions can be called without being bound to the provider.
  16. schedule(callback) {
  17. let request = requestAnimationFrame;
  18. let cancel: typeof cancelAnimationFrame | undefined = cancelAnimationFrame;
  19. const { delegate } = animationFrameProvider;
  20. if (delegate) {
  21. request = delegate.requestAnimationFrame;
  22. cancel = delegate.cancelAnimationFrame;
  23. }
  24. const handle = request((timestamp) => {
  25. // Clear the cancel function. The request has been fulfilled, so
  26. // attempting to cancel the request upon unsubscription would be
  27. // pointless.
  28. cancel = undefined;
  29. callback(timestamp);
  30. });
  31. return new Subscription(() => cancel?.(handle));
  32. },
  33. requestAnimationFrame(...args) {
  34. const { delegate } = animationFrameProvider;
  35. return (delegate?.requestAnimationFrame || requestAnimationFrame)(...args);
  36. },
  37. cancelAnimationFrame(...args) {
  38. const { delegate } = animationFrameProvider;
  39. return (delegate?.cancelAnimationFrame || cancelAnimationFrame)(...args);
  40. },
  41. delegate: undefined,
  42. };