[Perf] Fix slow animate function
This commit is contained in:
parent
a2b851e34c
commit
610574c23a
99
src/util/FrameDebugger.ts
Normal file
99
src/util/FrameDebugger.ts
Normal file
@ -0,0 +1,99 @@
|
||||
const RANDOM = 0.95;
|
||||
const DEBOUNCE = 3000;
|
||||
|
||||
export default class FrameDebugger {
|
||||
private durations: number[] = [];
|
||||
|
||||
private startedAtByFrameKey: Record<string, number | undefined> = {};
|
||||
|
||||
private passedFrames: string[] = [];
|
||||
|
||||
private timeout: number | undefined;
|
||||
|
||||
constructor(private name: string = '[No name]') {
|
||||
}
|
||||
|
||||
onFrameStart(frameKey = '0') {
|
||||
if (this.passedFrames.includes(frameKey)) {
|
||||
// debugger
|
||||
}
|
||||
|
||||
if (this.startedAtByFrameKey[frameKey]) {
|
||||
return;
|
||||
}
|
||||
|
||||
this.startedAtByFrameKey[frameKey] = performance.now();
|
||||
}
|
||||
|
||||
onFrameEnd(frameKey = '0', onAnimationEnd?: AnyToVoidFunction) {
|
||||
if (!this.startedAtByFrameKey[frameKey]) {
|
||||
return;
|
||||
}
|
||||
|
||||
const duration = performance.now() - this.startedAtByFrameKey[frameKey]!;
|
||||
|
||||
if (this.passedFrames.includes(frameKey)) {
|
||||
// debugger
|
||||
}
|
||||
|
||||
this.passedFrames.push(frameKey);
|
||||
this.durations.push(duration);
|
||||
|
||||
this.startedAtByFrameKey[frameKey] = undefined;
|
||||
|
||||
if (Math.random() < RANDOM) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (this.timeout) {
|
||||
clearTimeout(this.timeout);
|
||||
}
|
||||
|
||||
// eslint-disable-next-line no-restricted-globals
|
||||
this.timeout = self.setTimeout(() => {
|
||||
if (!this.durations.length) {
|
||||
return;
|
||||
}
|
||||
|
||||
const max = Math.max(...this.durations);
|
||||
const min = Math.max(...this.durations);
|
||||
const maxIndex = this.durations.indexOf(max);
|
||||
const minIndex = this.durations.indexOf(min);
|
||||
const reduced = this.durations.slice();
|
||||
reduced.splice(maxIndex, 1);
|
||||
reduced.splice(minIndex, 1);
|
||||
const avg = reduced.reduce((acc, cur) => acc + cur, 0) / this.durations.length;
|
||||
|
||||
// eslint-disable-next-line no-console
|
||||
console.log(
|
||||
'!!!',
|
||||
this.name,
|
||||
'total frames:',
|
||||
this.durations.length,
|
||||
', avg duration:',
|
||||
avg.toFixed(2),
|
||||
', max duration:',
|
||||
Math.max(...reduced).toFixed(2),
|
||||
', min duration:',
|
||||
Math.min(...reduced).toFixed(2),
|
||||
);
|
||||
|
||||
onAnimationEnd?.();
|
||||
|
||||
this.reset();
|
||||
}, DEBOUNCE);
|
||||
}
|
||||
|
||||
reset() {
|
||||
this.durations = [];
|
||||
|
||||
this.startedAtByFrameKey = {};
|
||||
|
||||
this.passedFrames = [];
|
||||
|
||||
if (this.timeout) {
|
||||
clearTimeout(this.timeout);
|
||||
this.timeout = undefined;
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -24,9 +24,17 @@ export function animateSingle(tick: Function, instance?: AnimationInstance) {
|
||||
}
|
||||
|
||||
export function animate(tick: Function) {
|
||||
fastRaf(() => {
|
||||
if (tick()) {
|
||||
animate(tick);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
export function animateInstantly(tick: Function) {
|
||||
if (tick()) {
|
||||
fastRaf(() => {
|
||||
animate(tick);
|
||||
animateInstantly(tick);
|
||||
});
|
||||
}
|
||||
}
|
||||
@ -72,7 +80,7 @@ export function animateNumber({
|
||||
const t0 = Date.now();
|
||||
let canceled = false;
|
||||
|
||||
animate(() => {
|
||||
animateInstantly(() => {
|
||||
if (canceled) return false;
|
||||
const t1 = Date.now();
|
||||
let t = (t1 - t0) / duration;
|
||||
|
||||
@ -2,7 +2,6 @@ import { getGlobal } from '../global';
|
||||
|
||||
import { ANIMATION_LEVEL_MIN } from '../config';
|
||||
import { animate } from './animation';
|
||||
import { fastRaf } from './schedulers';
|
||||
|
||||
const DEFAULT_DURATION = 300;
|
||||
|
||||
@ -62,23 +61,21 @@ function scrollWithJs(container: HTMLElement, left: number, duration: number) {
|
||||
});
|
||||
const startAt = Date.now();
|
||||
|
||||
fastRaf(() => {
|
||||
animate(() => {
|
||||
if (isStopped) return false;
|
||||
animate(() => {
|
||||
if (isStopped) return false;
|
||||
|
||||
const t = Math.min((Date.now() - startAt) / duration, 1);
|
||||
const t = Math.min((Date.now() - startAt) / duration, 1);
|
||||
|
||||
const currentPath = path * (1 - transition(t));
|
||||
container.scrollLeft = Math.round(target - currentPath);
|
||||
const currentPath = path * (1 - transition(t));
|
||||
container.scrollLeft = Math.round(target - currentPath);
|
||||
|
||||
if (t >= 1) {
|
||||
container.style.scrollSnapType = '';
|
||||
container.dataset.scrollId = undefined;
|
||||
stopById.delete(id);
|
||||
resolve();
|
||||
}
|
||||
return t < 1;
|
||||
});
|
||||
if (t >= 1) {
|
||||
container.style.scrollSnapType = '';
|
||||
container.dataset.scrollId = undefined;
|
||||
stopById.delete(id);
|
||||
resolve();
|
||||
}
|
||||
return t < 1;
|
||||
});
|
||||
|
||||
return promise;
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user