75 lines
2.4 KiB
TypeScript
75 lines
2.4 KiB
TypeScript
/**
|
|
* @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;
|
|
};
|