In modern day web applications, the requirement to view certain contents in fullscreen mode is becoming pretty common. Sometimes, this need arises in contexts like image galleries, content editors, or other scenarios.
If you ever need to implement such a feature in Angular application, the easiest way to do this is by creating a directive to support fullscreen mode.
Let’s craft a versatile directive that can seamlessly attach to any HTML element, including the main HTML document. With its adaptability, this directive ensures compatibility with most modern-day browsers’ https://developer.mozilla.org/en-US/docs/Web/API/Fullscreen_API.
Fullscreen directive
import { DOCUMENT } from '@angular/common';
import {
Directive,
ElementRef,
EventEmitter,
HostBinding,
HostListener,
Inject,
Input,
Output,
} from '@angular/core';
export interface FullscreenTransition {
isFullscreen: boolean;
element: Element | null;
}
@Directive({
selector: '[fullscreen]',
exportAs: 'fullscreen',
})
export class FullscreenDirective {
private element!: HTMLElement;
@Input()
set fullscreen(element: HTMLElement | string) {
if (element instanceof ElementRef) {
this.element = element.nativeElement;
} else if (element instanceof HTMLElement) {
this.element = element;
} else if (element === '') {
this.element = this.doc.documentElement;
} else {
throw new Error(
`Only type HTMLElement or string allowed, got "${typeof element}".`
);
}
}
get fullscreen(): HTMLElement {
return this.element;
}
@HostBinding('class.fullscreen')
get isFullscreen(): boolean {
return this.isFullscreenEnabled();
}
@HostListener('document:fullscreenchange')
private onTransition() {
const isFullscreen = this.isFullscreen;
const element = this.element;
this.change.emit({ isFullscreen, element });
}
@Output()
change = new EventEmitter<FullscreenTransition>();
constructor(@Inject(DOCUMENT) private doc: Document) {}
async enter() {
if (this.fullscreen) {
await this.enterElementFullscreen(this.fullscreen);
} else {
await this.enterDocumentFullscreen();
}
}
async exit() {
if (this.isFullscreen) {
await this.exitFullscreen();
}
}
toggle() {
if (this.isFullscreen) {
this.exit();
} else {
this.enter();
}
}
private async enterDocumentFullscreen() {
const elem = this.doc.documentElement;
await this.enterFullscreen(elem);
}
private async exitDocumentFullscreen() {
await this.exitFullscreen();
}
private async enterElementFullscreen(elem: HTMLElement) {
await this.enterFullscreen(elem);
}
private async exitElementFullscreen() {
await this.exitFullscreen();
}
private async enterFullscreen(elem: HTMLElement) {
await ((elem as any).requestFullscreen?.() ||
(elem as any).webkitRequestFullscreen?.() ||
(elem as any).mozRequestFullScreen?.() ||
(elem as any).msRequestFullscreen?.());
}
private async exitFullscreen() {
await ((this.doc as any).exitFullscreen?.() ||
(this.doc as any).webkitExitFullscreen?.() ||
(this.doc as any).mozCancelFullScreen?.() ||
(this.doc as any).msExitFullscreen?.());
}
private isFullscreenEnabled(): boolean {
return !!(
(this.doc as any).fullscreenElement ||
(this.doc as any).webkitFullscreenElement ||
(this.doc as any).mozFullScreenElement ||
(this.doc as any).msFullscreenElement
);
}
}
Implementation of this directive is pretty straightforward.
Triggering the specific HTML element in fullscreen mode:
<div
#fullscreen
[fullscreen]="fullscreen"
(change)="onFullscreenChange($event)"
>
</div>
Triggering the entire HTML document in fullscreen mode:
<div
#fullscreen
fullscreen
(change)="onFullscreenChange($event)"
>
</div>
The HTML element bound to directive is getting a fullscreenCSS
class, to allow further styling of the element, if needed:
@HostBinding('class.fullscreen')
get isFullscreen(): boolean {
return this.isFullscreenEnabled();
}
Event changeemitter
can be used to track fullscreen transition:
@HostListener('document:fullscreenchange')
private onTransition() {
const isFullscreen = this.isFullscreen;
const element = this.element;
this.change.emit({ isFullscreen, element });
}
@Output()
change = new EventEmitter<FullscreenTransition>();
export interface FullscreenTransition {
isFullscreen: boolean;
element: Element | null;
}
onFullscreenChange(event: FullscreenTransition) {
this.isFullscreen = event.isFullscreen;
}
Incorporating fullscreen functionality into Angular applications using a custom directive offers users a seamless and immersive experience. By leveraging the flexibility and compatibility of modern browsers, developers can enhance the usability of their web applications. With the provided directive and accompanying demo, implementing fullscreen mode becomes easy, empowering developers to create dynamic and engaging user interfaces.
This is the final result of the demo application:
Top comments (0)