1
0
mirror of https://github.com/robonen/tools.git synced 2026-03-20 02:44:45 +00:00
Files
tools/vue/toolkit/src/composables/browser/useFps/index.ts

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,
};
}