36 lines
1.0 KiB
TypeScript
36 lines
1.0 KiB
TypeScript
"use client";
|
|||
|
|
|
||
|
|
import { useEffect, useState } from "react";
|
||
|
|
|
||
|
|
/** Self-contained rAF-based FPS counter — the engine exposes no perf API of its own. */
|
||
|
|
export default function StatsReadout() {
|
||
|
|
const [fps, setFps] = useState<number | null>(null);
|
||
|
|
|
||
|
|
useEffect(() => {
|
||
|
|
let frameCount = 0;
|
||
|
|
let windowStart = performance.now();
|
||
|
|
let raf = 0;
|
||
|
|
|
||
|
|
const tick = (now: number) => {
|
||
|
|
frameCount += 1;
|
||
|
|
const elapsed = now - windowStart;
|
||
|
|
if (elapsed >= 500) {
|
||
|
|
setFps(Math.round((frameCount * 1000) / elapsed));
|
||
|
|
frameCount = 0;
|
||
|
|
windowStart = now;
|
||
|
|
}
|
||
|
|
raf = requestAnimationFrame(tick);
|
||
|
|
};
|
||
|
|
raf = requestAnimationFrame(tick);
|
||
|
|
|
||
|
|
return () => cancelAnimationFrame(raf);
|
||
|
|
}, []);
|
||
|
|
|
||
|
|
return (
|
||
|
|
<div className="flex items-baseline gap-2 rounded border border-chrome/30 bg-black/40 px-3 py-1.5 font-mono">
|
||
|
|
<span className="text-xs tracking-widest text-chrome">FPS</span>
|
||
|
|
<span className="text-lg tabular-nums text-arc">{fps ?? "--"}</span>
|
||
|
|
</div>
|
||
|
|
);
|
||
|
|
}
|