Files
dwg-dxf-viewer-sample/apps/viewer-3d/src/ui/fps.ts
T
lectom bedb357259 chore(monorepo): import hmwebviewer history at a717900
git-subtree-dir: apps/viewer-3d
git-subtree-mainline: 5e10bb1be4
git-subtree-split: a71790070d
2026-07-29 09:04:52 +09:00

59 lines
1.6 KiB
TypeScript

/**
* On-screen FPS meter.
*
* Driven from the viewer's animate loop: call `sample(now)` once per frame with
* the requestAnimationFrame timestamp. It computes an instantaneous fps from the
* inter-frame delta, smooths it into a rolling average (EMA), and throttles DOM
* writes to ~every 250ms so updating the overlay doesn't itself cause jank.
* Kept dependency-free in the src/ui/progress.ts style.
*/
const DOM_INTERVAL_MS = 250;
// EMA smoothing factor: higher = more responsive, lower = smoother.
const EMA_ALPHA = 0.1;
export interface FpsMeter {
/** Overlay element; the viewer appends this to its container. */
el: HTMLElement;
/** Feed one frame timestamp (DOMHighResTimeStamp). */
sample(now: number): void;
/** Current rolling-average fps. */
fps(): number;
}
/** Create an FPS overlay element + sampler. */
export function createFpsMeter(): FpsMeter {
const el = document.createElement("div");
el.className = "fps";
el.textContent = "-- FPS";
let last = 0;
let avg = 0;
let lastDom = 0;
return {
el,
sample(now: number): void {
if (last === 0) {
last = now;
return;
}
const dt = now - last;
last = now;
if (dt <= 0) return;
const inst = 1000 / dt;
avg = avg === 0 ? inst : avg + EMA_ALPHA * (inst - avg);
if (now - lastDom >= DOM_INTERVAL_MS) {
lastDom = now;
const v = Math.round(avg);
el.textContent = `${v} FPS`;
el.style.color = v >= 60 ? "#5cff5c" : v >= 30 ? "#ffb74a" : "#ff5c5c";
}
},
fps(): number {
return avg;
},
};
}