move.gl
Version:
Motion and Animation Library for Stylescape.
193 lines (177 loc) • 6.02 kB
text/typescript
// ============================================================================
// move.gl | Screensaver
// ============================================================================
// Copyright 2025 Scape Agency BV
// Licensed under MIT License
// ============================================================================
/**
* Screensaver Configuration Options
*/
export interface ScreensaverOptions {
/** Inactivity timeout in milliseconds */
timeout: number;
/** URL for the video to play */
videoUrl?: string;
/** URL for the audio to play */
audioUrl?: string;
/** ID of the screensaver container element */
containerId?: string;
/** ID of the video element */
videoId?: string;
/** ID of the audio element */
audioId?: string;
}
/**
* Screensaver Class
*
* Handles the activation and deactivation of a screensaver based on
* user inactivity. Provides methods to start and stop the screensaver,
* manage media sources, and handle user interactions.
*
* @example
* ```typescript
* const screensaver = new Screensaver({
* timeout: 300000, // 5 minutes
* videoUrl: 'path/to/video.mp4',
* audioUrl: 'path/to/audio.mp3'
* });
* screensaver.setVolume(0.5);
* ```
*/
export class Screensaver {
private timeoutId: number | undefined;
private readonly timeout: number;
private screensaverElement: HTMLElement | null = null;
private videoElement: HTMLVideoElement | null = null;
private audioElement: HTMLAudioElement | null = null;
private isActive: boolean = false;
private readonly options: ScreensaverOptions;
/**
* Creates a new Screensaver instance.
* @param options - Configuration options for the screensaver.
*/
constructor(options: ScreensaverOptions) {
this.options = {
containerId: 'screensaver',
videoId: 'screensaverVideo',
audioId: 'screensaverAudio',
...options
};
this.timeout = options.timeout;
this.initializeElements();
if (options.videoUrl && options.audioUrl) {
this.loadMedia(options.videoUrl, options.audioUrl);
}
this.setupEventListeners();
this.startScreensaverTimeout();
}
/**
* Initializes HTML elements from the DOM.
*/
private initializeElements(): void {
this.screensaverElement = document.getElementById(this.options.containerId!);
this.videoElement = document.getElementById(this.options.videoId!) as HTMLVideoElement | null;
this.audioElement = document.getElementById(this.options.audioId!) as HTMLAudioElement | null;
}
/**
* Loads media sources into the video and audio elements.
* @param videoUrl - The source URL of the video.
* @param audioUrl - The source URL of the audio.
*/
private loadMedia(videoUrl: string, audioUrl: string): void {
if (this.videoElement) {
this.videoElement.src = videoUrl;
}
if (this.audioElement) {
this.audioElement.src = audioUrl;
}
}
/**
* @notice Sets up event listeners for user interaction to prevent
* screensaver activation.
* @dev Listens for 'mousemove', 'keydown', and 'touchstart' events
* to reset the screensaver timer.
*/
private setupEventListeners() {
['mousemove', 'keydown', 'touchstart'].forEach(event => {
document.addEventListener(event, this.resetScreensaver);
});
}
/**
* @notice Starts or restarts the screensaver timeout.
* @dev Resets any existing timeout and sets a new timeout to activate
* the screensaver.
*/
private startScreensaverTimeout() {
this.stopScreensaver(); // Stop existing screensaver if active
this.timeoutId = window.setTimeout(
() => this.activateScreensaver(), this.timeout
);
}
/**
* @notice Resets the screensaver timer and stops the screensaver if
* active.
* @dev Called upon user interactions detected by event listeners.
*/
private resetScreensaver = () => {
if (this.isActive) {
this.stopScreensaver();
}
this.startScreensaverTimeout();
};
/**
* Activates the screensaver, displaying elements and playing media.
*/
private activateScreensaver = (): void => {
if (this.screensaverElement) {
this.screensaverElement.style.display = 'block';
}
this.videoElement?.play();
this.audioElement?.play();
this.isActive = true;
};
/**
* Stops the screensaver and hides its elements.
*/
public stopScreensaver(): void {
if (this.screensaverElement) {
this.screensaverElement.style.display = 'none';
}
this.videoElement?.pause();
this.audioElement?.pause();
this.isActive = false;
if (this.timeoutId !== undefined) {
clearTimeout(this.timeoutId);
this.timeoutId = undefined;
}
}
/**
* Sets the volume for both video and audio elements.
* @param volume - A number between 0.0 and 1.0 indicating the volume level.
*/
public setVolume(volume: number): void {
const clampedVolume = Math.max(0, Math.min(1, volume));
if (this.videoElement) {
this.videoElement.volume = clampedVolume;
}
if (this.audioElement) {
this.audioElement.volume = clampedVolume;
}
}
/**
* Returns whether the screensaver is currently active.
*/
public getIsActive(): boolean {
return this.isActive;
}
/**
* Cleans up event listeners and stops the screensaver.
*/
public destroy(): void {
this.stopScreensaver();
['mousemove', 'keydown', 'touchstart'].forEach(event => {
document.removeEventListener(event, this.resetScreensaver);
});
}
}
export default Screensaver;