mirror of
https://github.com/robonen/tools.git
synced 2026-03-20 02:44:45 +00:00
110 lines
2.3 KiB
TypeScript
110 lines
2.3 KiB
TypeScript
import type { ConfigurableWindow, ResumableActions, ResumableOptions } from '@/types';
|
|
import type { UseRafFnCallbackArgs } from '@/composables/browser/useRafFn';
|
|
import type { Ref } from 'vue';
|
|
import { ref } from 'vue';
|
|
import { useRafFn } from '@/composables/browser/useRafFn';
|
|
|
|
export interface UseFpsOptions extends ResumableOptions, ConfigurableWindow {
|
|
/**
|
|
* Number of frames to average over for a smoother reading.
|
|
*
|
|
* @default 10
|
|
*/
|
|
every?: number;
|
|
}
|
|
|
|
export interface UseFpsReturn extends ResumableActions {
|
|
/**
|
|
* Current frames per second (averaged over the last `every` frames)
|
|
*/
|
|
fps: Readonly<Ref<number>>;
|
|
|
|
/**
|
|
* Minimum FPS recorded since the composable was created or last reset
|
|
*/
|
|
min: Readonly<Ref<number>>;
|
|
|
|
/**
|
|
* Maximum FPS recorded since the composable was created or last reset
|
|
*/
|
|
max: Readonly<Ref<number>>;
|
|
|
|
/**
|
|
* Whether the FPS counter is currently active
|
|
*/
|
|
isActive: Readonly<Ref<boolean>>;
|
|
|
|
/**
|
|
* Reset min/max tracking
|
|
*/
|
|
reset: () => void;
|
|
}
|
|
|
|
/**
|
|
* Reactive FPS counter based on `requestAnimationFrame`.
|
|
* Reports a smoothed FPS value averaged over a configurable number of frames,
|
|
* and tracks min/max values.
|
|
*
|
|
* @param options - Configuration options
|
|
*
|
|
* @example
|
|
* ```ts
|
|
* const { fps, min, max, reset } = useFps();
|
|
* ```
|
|
*/
|
|
export function useFps(options: UseFpsOptions = {}): UseFpsReturn {
|
|
const { every = 10, ...rafOptions } = options;
|
|
|
|
const fps = ref(0);
|
|
const min = ref(Infinity);
|
|
const max = ref(0);
|
|
|
|
let deltaSum = 0;
|
|
let frameCount = 0;
|
|
|
|
function update({ delta }: UseRafFnCallbackArgs) {
|
|
if (!delta)
|
|
return;
|
|
|
|
deltaSum += delta;
|
|
frameCount++;
|
|
|
|
if (frameCount < every)
|
|
return;
|
|
|
|
const currentFps = Math.round(1000 / (deltaSum / frameCount));
|
|
|
|
fps.value = currentFps;
|
|
|
|
if (currentFps < min.value)
|
|
min.value = currentFps;
|
|
|
|
if (currentFps > max.value)
|
|
max.value = currentFps;
|
|
|
|
deltaSum = 0;
|
|
frameCount = 0;
|
|
}
|
|
|
|
function reset() {
|
|
min.value = Infinity;
|
|
max.value = 0;
|
|
fps.value = 0;
|
|
deltaSum = 0;
|
|
frameCount = 0;
|
|
}
|
|
|
|
const { isActive, pause, resume, toggle } = useRafFn(update, rafOptions);
|
|
|
|
return {
|
|
fps,
|
|
min,
|
|
max,
|
|
isActive,
|
|
reset,
|
|
pause,
|
|
resume,
|
|
toggle,
|
|
};
|
|
}
|