aboutsummaryrefslogtreecommitdiffstats
path: root/node_modules/rxjs/src/internal/observable/dom/animationFrames.ts
diff options
context:
space:
mode:
Diffstat (limited to 'node_modules/rxjs/src/internal/observable/dom/animationFrames.ts')
-rw-r--r--node_modules/rxjs/src/internal/observable/dom/animationFrames.ts132
1 files changed, 132 insertions, 0 deletions
diff --git a/node_modules/rxjs/src/internal/observable/dom/animationFrames.ts b/node_modules/rxjs/src/internal/observable/dom/animationFrames.ts
new file mode 100644
index 0000000..38b338b
--- /dev/null
+++ b/node_modules/rxjs/src/internal/observable/dom/animationFrames.ts
@@ -0,0 +1,132 @@
+import { Observable } from '../../Observable';
+import { TimestampProvider } from '../../types';
+import { performanceTimestampProvider } from '../../scheduler/performanceTimestampProvider';
+import { animationFrameProvider } from '../../scheduler/animationFrameProvider';
+
+/**
+ * An observable of animation frames
+ *
+ * Emits the amount of time elapsed since subscription and the timestamp on each animation frame.
+ * Defaults to milliseconds provided to the requestAnimationFrame's callback. Does not end on its own.
+ *
+ * Every subscription will start a separate animation loop. Since animation frames are always scheduled
+ * by the browser to occur directly before a repaint, scheduling more than one animation frame synchronously
+ * should not be much different or have more overhead than looping over an array of events during
+ * a single animation frame. However, if for some reason the developer would like to ensure the
+ * execution of animation-related handlers are all executed during the same task by the engine,
+ * the `share` operator can be used.
+ *
+ * This is useful for setting up animations with RxJS.
+ *
+ * ## Examples
+ *
+ * Tweening a div to move it on the screen
+ *
+ * ```ts
+ * import { animationFrames, map, takeWhile, endWith } from 'rxjs';
+ *
+ * function tween(start: number, end: number, duration: number) {
+ * const diff = end - start;
+ * return animationFrames().pipe(
+ * // Figure out what percentage of time has passed
+ * map(({ elapsed }) => elapsed / duration),
+ * // Take the vector while less than 100%
+ * takeWhile(v => v < 1),
+ * // Finish with 100%
+ * endWith(1),
+ * // Calculate the distance traveled between start and end
+ * map(v => v * diff + start)
+ * );
+ * }
+ *
+ * // Setup a div for us to move around
+ * const div = document.createElement('div');
+ * document.body.appendChild(div);
+ * div.style.position = 'absolute';
+ * div.style.width = '40px';
+ * div.style.height = '40px';
+ * div.style.backgroundColor = 'lime';
+ * div.style.transform = 'translate3d(10px, 0, 0)';
+ *
+ * tween(10, 200, 4000).subscribe(x => {
+ * div.style.transform = `translate3d(${ x }px, 0, 0)`;
+ * });
+ * ```
+ *
+ * Providing a custom timestamp provider
+ *
+ * ```ts
+ * import { animationFrames, TimestampProvider } from 'rxjs';
+ *
+ * // A custom timestamp provider
+ * let now = 0;
+ * const customTSProvider: TimestampProvider = {
+ * now() { return now++; }
+ * };
+ *
+ * const source$ = animationFrames(customTSProvider);
+ *
+ * // Log increasing numbers 0...1...2... on every animation frame.
+ * source$.subscribe(({ elapsed }) => console.log(elapsed));
+ * ```
+ *
+ * @param timestampProvider An object with a `now` method that provides a numeric timestamp
+ */
+export function animationFrames(timestampProvider?: TimestampProvider) {
+ return timestampProvider ? animationFramesFactory(timestampProvider) : DEFAULT_ANIMATION_FRAMES;
+}
+
+/**
+ * Does the work of creating the observable for `animationFrames`.
+ * @param timestampProvider The timestamp provider to use to create the observable
+ */
+function animationFramesFactory(timestampProvider?: TimestampProvider) {
+ return new Observable<{ timestamp: number; elapsed: number }>((subscriber) => {
+ // If no timestamp provider is specified, use performance.now() - as it
+ // will return timestamps 'compatible' with those passed to the run
+ // callback and won't be affected by NTP adjustments, etc.
+ const provider = timestampProvider || performanceTimestampProvider;
+
+ // Capture the start time upon subscription, as the run callback can remain
+ // queued for a considerable period of time and the elapsed time should
+ // represent the time elapsed since subscription - not the time since the
+ // first rendered animation frame.
+ const start = provider.now();
+
+ let id = 0;
+ const run = () => {
+ if (!subscriber.closed) {
+ id = animationFrameProvider.requestAnimationFrame((timestamp: DOMHighResTimeStamp | number) => {
+ id = 0;
+ // Use the provider's timestamp to calculate the elapsed time. Note that
+ // this means - if the caller hasn't passed a provider - that
+ // performance.now() will be used instead of the timestamp that was
+ // passed to the run callback. The reason for this is that the timestamp
+ // passed to the callback can be earlier than the start time, as it
+ // represents the time at which the browser decided it would render any
+ // queued frames - and that time can be earlier the captured start time.
+ const now = provider.now();
+ subscriber.next({
+ timestamp: timestampProvider ? now : timestamp,
+ elapsed: now - start,
+ });
+ run();
+ });
+ }
+ };
+
+ run();
+
+ return () => {
+ if (id) {
+ animationFrameProvider.cancelAnimationFrame(id);
+ }
+ };
+ });
+}
+
+/**
+ * In the common case, where the timestamp provided by the rAF API is used,
+ * we use this shared observable to reduce overhead.
+ */
+const DEFAULT_ANIMATION_FRAMES = animationFramesFactory();
send patches to the email below
yukais@pinapelz.com
include the subject [PATCH repo_name]
pinapelz.com
homepage