Fps

Reactive FPS (Frames Per Second) monitor using requestAnimationFrame. Track rendering performance with Angular signals.

Loading demo...

Usage

angular-ts
import { Component } from '@angular/core';
import { fps } from '@signality/core';

@Component({
  template: `<p>FPS: {{ fpsMonitor.fps() }}</p>`,
})
export class FpsDisplay {
  readonly fpsMonitor = fps(); 
}

Use InjectionToken for Singleton

For global state tracking like fps, consider using the provided FPS token instead of calling the function directly. This provides a singleton instance that can be shared across your entire application, reducing memory usage and event listener overhead:

typescript
import { inject } from '@angular/core';
import { FPS } from '@signality/core';

const fpsMonitor = fps(); 
const fpsMonitor = inject(FPS); 

Learn more about Token-based utilities.

Parameters

ParameterTypeDescription
optionsFpsOptionsOptional configuration (see Options below)

Options

OptionTypeDefaultDescription
immediatebooleantrueStart monitoring immediately
sampleSizenumber60Number of frames to average
injectorInjector-Optional injector for DI context

Return Value

The fps() function returns an FpsRef object:

PropertyTypeDescription
fpsSignal<number>Current frames per second
isRunningSignal<boolean>Whether monitoring is active
start() => voidStart FPS monitoring
stop() => voidStop FPS monitoring

Examples

Performance monitor

angular-ts
import { Component, computed } from '@angular/core';
import { fps } from '@signality/core';

@Component({
  template: `
    <div class="fps-monitor" [class]="performanceClass()">
      <span class="fps-value">{{ fpsMonitor.fps() }}</span>
      <span class="fps-label">FPS</span>
    </div>
  `,
})
export class PerformanceMonitor {
  readonly fpsMonitor = fps(); 
  
  readonly performanceClass = computed(() => {
    const currentFps = this.fpsMonitor.fps();
    if (currentFps >= 55) return 'good';
    if (currentFps >= 30) return 'medium';
    return 'poor';
  });
}

Adaptive quality

angular-ts
import { Component, signal, effect } from '@angular/core';
import { fps } from '@signality/core';

type Quality = 'high' | 'medium' | 'low';

@Component({
  template: `
    <canvas #canvas></canvas>
    <p>Quality: {{ quality() }}</p>
  `,
})
export class AdaptiveRenderer {
  readonly fpsMonitor = fps();
  readonly quality = signal<Quality>('high');
  
  constructor() {
    effect(() => {
      const currentFps = this.fpsMonitor.fps();
      
      // Automatically adjust quality based on FPS
      if (currentFps < 25 && this.quality() !== 'low') {
        this.quality.set('low');
      } else if (currentFps < 45 && this.quality() === 'high') {
        this.quality.set('medium');
      } else if (currentFps >= 55 && this.quality() !== 'high') {
        this.quality.set('high');
      }
    });
  }
}

SSR Compatibility

On the server, signals initialize with safe defaults:

  • fps0
  • isRunningfalse
  • start, stop → no-op functions

Type Definitions

typescript
interface FpsOptions extends WithInjector {
  readonly immediate?: boolean;
  readonly sampleSize?: number;
}

interface FpsRef {
  readonly fps: Signal<number>;
  readonly isRunning: Signal<boolean>;
  readonly start: () => void;
  readonly stop: () => void;
}

function fps(options?: FpsOptions): FpsRef;
Edit this page on GitHub Last updated: Mar 19, 2026, 23:28:23