main code
This commit is contained in:
74
shared/components/src/utils/rafQueue.ts
Normal file
74
shared/components/src/utils/rafQueue.ts
Normal file
@@ -0,0 +1,74 @@
|
||||
/**
|
||||
* @name RequestAnimationFrameLimiter
|
||||
* @description
|
||||
* allows for multiple callbacks to be called
|
||||
* within a single RAF function.
|
||||
* It also spreads long running tasks across multiple
|
||||
* microtask to help keep the main thread free for user interactions
|
||||
*
|
||||
*/
|
||||
export class RequestAnimationFrameLimiter {
|
||||
private queue: Array<(timestamp?: number) => void>;
|
||||
private RAF_FN_LIMIT_MS: number;
|
||||
private requestId: number | null;
|
||||
constructor() {
|
||||
this.queue = [];
|
||||
// ideal limit for scroll based animations: https://developers.google.com/web/fundamentals/performance/rendering/optimize-javascript-execution#reduce_complexity_or_use_web_workers
|
||||
this.RAF_FN_LIMIT_MS = 3;
|
||||
this.requestId = null;
|
||||
}
|
||||
|
||||
private flush(): void {
|
||||
this.requestId =
|
||||
this.queue.length === 0
|
||||
? null
|
||||
: window.requestAnimationFrame((timestamp) => {
|
||||
const start = window.performance.now();
|
||||
let ellapsedTime = 0;
|
||||
const { RAF_FN_LIMIT_MS } = this;
|
||||
let count = 0;
|
||||
|
||||
while (
|
||||
count < this.queue.length &&
|
||||
ellapsedTime < RAF_FN_LIMIT_MS
|
||||
) {
|
||||
let item = this.queue[count];
|
||||
if (item) {
|
||||
item(timestamp);
|
||||
}
|
||||
const finishTime = window.performance.now();
|
||||
|
||||
count = count + 1;
|
||||
ellapsedTime = finishTime - start;
|
||||
}
|
||||
const newQueue = this.queue.slice(count);
|
||||
|
||||
this.queue = newQueue;
|
||||
this.flush();
|
||||
});
|
||||
}
|
||||
public add(callback: () => void): void {
|
||||
this.queue.push(callback);
|
||||
if (this.requestId === null) {
|
||||
this.flush();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
let raf: RequestAnimationFrameLimiter | ServerSafeRAFLimiter = null;
|
||||
|
||||
type ServerSafeRAFLimiter = {
|
||||
add: (callback: () => void) => void;
|
||||
};
|
||||
|
||||
export const getRafQueue = () => {
|
||||
if (typeof window === 'undefined') {
|
||||
// SSR safe
|
||||
raf = {
|
||||
add: (callback: () => void) => callback(),
|
||||
};
|
||||
} else if (raf === null) {
|
||||
raf = new RequestAnimationFrameLimiter();
|
||||
}
|
||||
return raf;
|
||||
};
|
||||
Reference in New Issue
Block a user