nplayer
Version:
powerful danmaku video player
147 lines (123 loc) • 3.86 kB
text/typescript
import { CLASS_PLAYER, EVENT } from '../constants';
import { Player } from '../player';
import { Disposable } from '../types';
import {
addClass, addDisposable, addDisposableListener, dispose, isFunction, isIOS, removeClass,
} from '../utils';
const CLASS_FULL = '-full';
export class Fullscreen implements Disposable {
private target!: HTMLElement;
private readonly prefix = this.getPrefix();
constructor(private player: Player) {
addDisposableListener(this, document, this.prefix === 'ms' ? 'MSFullscreenChange' : `${this.prefix}fullscreenchange` as any, () => {
let evt = '';
if (this.isActive) {
this.addClass();
evt = EVENT.ENTER_FULLSCREEN;
} else {
this.removeClass();
evt = EVENT.EXIT_FULLSCREEN;
}
this.player.emit(evt);
this.player.emit(EVENT.UPDATE_SIZE);
});
addDisposable(this, player.on(EVENT.UPDATE_OPTIONS, () => {
this.disableDblclick();
}));
this.setTarget();
if (this.isActive) this.addClass();
if (!player.opts.isTouch) {
this.enableDblclick();
}
}
private getPrefix(): string {
if (isFunction(document.exitFullscreen)) return '';
let prefix = '';
['webkit', 'moz', 'ms'].forEach((p) => {
if (
isFunction((document as any)[`${p}ExitFullscreen`])
|| isFunction((document as any)[`${p}CancelFullScreen`])
) {
prefix = p;
}
});
return prefix;
}
get requestFullscreen(): Element['requestFullscreen'] {
return (
HTMLElement.prototype.requestFullscreen
|| (HTMLElement.prototype as any).webkitRequestFullscreen
|| (HTMLElement.prototype as any).mozRequestFullScreen
|| (HTMLElement.prototype as any).msRequestFullscreen
);
}
get exitFullscreen(): Document['exitFullscreen'] {
return (
HTMLDocument.prototype.exitFullscreen
|| (HTMLDocument.prototype as any).webkitExitFullscreen
|| (HTMLDocument.prototype as any).cancelFullScreen
|| (HTMLDocument.prototype as any).mozCancelFullScreen
|| (HTMLDocument.prototype as any).msExitFullscreen
);
}
get fullscreenElement(): HTMLElement {
return (
document.fullscreenElement
|| (document as any).mozFullScreenElement
|| (document as any).msFullscreenElement
|| (document as any).webkitFullscreenElement
);
}
get isActive(): boolean {
return this.fullscreenElement === this.target;
}
private addClass(): void {
addClass(this.player.el, CLASS_FULL, CLASS_PLAYER);
}
private removeClass(): void {
removeClass(this.player.el, CLASS_FULL, CLASS_PLAYER);
}
enableDblclick(): void {
this.player.video.addEventListener('dblclick', this.toggle);
}
disableDblclick(): void {
this.player.video.removeEventListener('dblclick', this.toggle);
}
setTarget(dom?: HTMLElement, video?: HTMLVideoElement): void {
this.target = (dom && isIOS ? video : dom) || (isIOS ? this.player.video : this.player.el);
if (this.isActive) this.enter();
}
enter(): void {
if (isIOS) {
(this.target as any).webkitEnterFullscreen();
} else {
this.requestFullscreen.call(this.target, { navigationUI: 'hide' });
this.player.emit(EVENT.UPDATE_SIZE);
}
}
exit(): boolean {
if (!this.isActive) return false;
if (isIOS) {
(this.target as any).webkitExitFullscreen();
} else {
this.exitFullscreen.call(document);
this.player.emit(EVENT.UPDATE_SIZE);
}
return true;
}
toggle = (): void => {
if (this.isActive) {
this.exit();
} else {
this.enter();
}
}
dispose(): void {
if (!this.player) return;
this.player.off(EVENT.ENTER_FULLSCREEN);
this.player.off(EVENT.EXIT_FULLSCREEN);
this.disableDblclick();
this.player = null!;
dispose(this);
}
}