UNPKG

ion-video-player

Version:

HTML video player for Ionic 6 applications using angular

250 lines (243 loc) 23.3 kB
import * as i0 from '@angular/core'; import { Pipe, EventEmitter, Component, ViewChild, Input, Output, NgModule } from '@angular/core'; import * as i1 from '@angular/common'; import { CommonModule } from '@angular/common'; import * as i2 from '@ionic/angular'; import { IonicModule } from '@ionic/angular'; class SecondsToHoursPipe { transform(value) { return new Date(value * 1000).toISOString().substring(11, 19); } } SecondsToHoursPipe.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "15.0.1", ngImport: i0, type: SecondsToHoursPipe, deps: [], target: i0.ɵɵFactoryTarget.Pipe }); SecondsToHoursPipe.ɵpipe = i0.ɵɵngDeclarePipe({ minVersion: "14.0.0", version: "15.0.1", ngImport: i0, type: SecondsToHoursPipe, name: "secondsToHours" }); i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "15.0.1", ngImport: i0, type: SecondsToHoursPipe, decorators: [{ type: Pipe, args: [{ name: 'secondsToHours' }] }] }); class IonVideoPlayerComponent { constructor() { this.isPlaying = false; this.volume = 100; //Output Events this.play = new EventEmitter(); this.pause = new EventEmitter(); this.ended = new EventEmitter(); this.volumechange = new EventEmitter(); this.playing = new EventEmitter(); this.error = new EventEmitter(); } ngOnChanges() { } setVolume() { if (this.volumeBar.nativeElement.value == '100') { this.volume = 1; } else { this.volume = parseFloat('0.' + (this.volumeBar.nativeElement.value)); } this.videoPlayer.nativeElement.volume = this.volume; } playPauseVideo() { if (this.videoPlayer.nativeElement.paused || this.videoPlayer.nativeElement.ended) { // Change the button to a pause button this.videoPlayer.nativeElement.play(); this.isPlaying = true; } else { // Change the button to a play button this.videoPlayer.nativeElement.pause(); this.isPlaying = false; } } // Stop the current media from playing, and return it to the start position stopVideo() { this.videoPlayer.nativeElement.pause(); this.isPlaying = false; if (this.videoPlayer.nativeElement.currentTime) this.videoPlayer.nativeElement.currentTime = 0; } // Toggles the media player's mute and unmute status muteVolume() { if (this.videoPlayer.nativeElement.muted) { this.videoPlayer.nativeElement.muted = false; this.volume = this.videoPlayer.nativeElement.volume; } else { this.videoPlayer.nativeElement.muted = true; this.volume = 0; } } // Replays the media currently loaded in the player replayVideo() { this.resetPlayer(); this.videoPlayer.nativeElement.play(); } // Update the progress bar updateProgressBar() { // Work out how much of the media has played via the duration and currentTime parameters var percentage = Math.floor((100 / this.videoPlayer.nativeElement.duration) * this.videoPlayer.nativeElement.currentTime); // Update the progress bar's value if (this.options.controls) { this.progressBar.nativeElement.value = percentage; } } seek(e) { var percent = e.offsetX / this.progressBar.nativeElement.offsetWidth; this.videoPlayer.nativeElement.currentTime = percent * this.videoPlayer.nativeElement.duration; e.target.value = Math.floor(percent / 100); e.target.innerHTML = this.progressBar.nativeElement.value + '% played'; } //replay Video from start resetPlayer() { this.progressBar.nativeElement.value = 0; // Move the media back to the start this.videoPlayer.nativeElement.currentTime = 0; } //Open Player in Full screen mode toggleFullScreen() { if (document.fullscreenElement) { document.exitFullscreen(); } else { if (this.playerContainer.nativeElement.requestFullscreen) { this.playerContainer.nativeElement.requestFullscreen(); } else if (this.playerContainer.nativeElement.webkitRequestFullscreen) { /* Safari */ this.playerContainer.nativeElement.webkitRequestFullscreen(); } else if (this.playerContainer.nativeElement.msRequestFullscreen) { /* IE11 */ this.playerContainer.nativeElement.msRequestFullscreen(); } } } async openPip() { try { if (!document.pictureInPictureElement) { this.videoPlayer.nativeElement.requestPictureInPicture(); } else { document.exitPictureInPicture(); } } catch (reason) { console.error(reason); } } // Fires when the audio/video has been started or is no longer paused onPlay() { console.log('onPlay'); this.play.emit(); } // Fires when the audio/video has been paused onPause() { console.log('onPause'); this.pause.emit(); } // Fires when the current playlist is ended onEnded() { console.log('onEnded'); this.ended.emit(); } // Fires when the volume has been changed onVolumechange() { console.log('onVolumechange'); this.volumechange.emit(); } onPlaying() { console.log('onPlaying'); this.playing.emit(); } onError() { console.log('onError'); this.error.emit(); } onProgress() { // this.videoPlayer.nativeElement.addEventListener('progress', () => { // const duration = this.videoPlayer.nativeElement.duration; // console.log(duration) // if (duration > 0) { // for (let i = 0; i < this.videoPlayer.nativeElement.buffered.length; i++) { // if ( // this.videoPlayer.nativeElement.buffered.start(this.videoPlayer.nativeElement.buffered.length - 1 - i) < // this.videoPlayer.nativeElement.currentTime // ) { // console.log( // (this.videoPlayer.nativeElement.buffered.end(this.videoPlayer.nativeElement.buffered.length - 1 - i) * 100) / duration // ); // break; // } // } // } // }); } } IonVideoPlayerComponent.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "15.0.1", ngImport: i0, type: IonVideoPlayerComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); IonVideoPlayerComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "15.0.1", type: IonVideoPlayerComponent, selector: "ion-video-player", inputs: { options: "options" }, outputs: { play: "play", pause: "pause", ended: "ended", volumechange: "volumechange", playing: "playing", error: "error" }, viewQueries: [{ propertyName: "playerContainer", first: true, predicate: ["playerContainer"], descendants: true }, { propertyName: "videoPlayer", first: true, predicate: ["player"], descendants: true }, { propertyName: "progressBar", first: true, predicate: ["progressBar"], descendants: true }, { propertyName: "volumeBar", first: true, predicate: ["volumeBar"], descendants: true }], usesOnChanges: true, ngImport: i0, template: "<div id=\"player\" #playerContainer class=\"ion-video-player\">\n <video id=\"video-element\" #player\n (timeupdate)=\"updateProgressBar()\"\n [poster]=\"options.poster\"\n [autoplay]=\"options.autoplay\"\n [muted]=\"options.muted\"\n (play)=\"onPlay()\"\n (pause)=\"onPause()\"\n (ended)=\"onEnded()\"\n (volumechange)=\"onVolumechange()\"\n (playing)=\"onPlaying()\"\n (error)=\"onError()\"\n (progress)=\"onProgress()\">\n <source [src]=\"options.src\" [type]=\"options.type\">\n </video>\n\n <div id=\"controls\" *ngIf=\"options.controls\">\n\n <progress id=\"progress-bar\" (click)=\"seek($event)\" min=\"0\" max=\"100\" value='1' #progressBar></progress>\n\n <div class=\"controls-btns\">\n <div class=\"start-stop\">\n <ion-button fill=\"clear\" size=\"small\" slot=\"icon-only\" class='play' (click)=\"playPauseVideo()\">\n <ion-icon [name]=\"isPlaying ? 'pause' : 'play'\"></ion-icon>\n </ion-button>\n <span *ngIf=\"player.duration\">\n {{player.currentTime | secondsToHours}} / {{player.duration | secondsToHours }}\n </span>\n </div>\n\n <div class=\"volume-box\">\n <input type=\"range\" class=\"volumeRange\"\n (change)=\"setVolume()\" \n min=\"0\"\n max=\"100\"\n step=\"1\"\n [value]=\"volumeBar.value\"\n #volumeBar\n [ngStyle]=\"{\n 'background-size': volumeBar.value + '% 100%'\n }\"\n />\n\n <ion-button fill=\"clear\" size=\"small\" slot=\"icon-only\" class=\"mute\" title=\"mute\" (click)=\"muteVolume()\">\n <ion-icon [name]=\"\n volume == 0 ? 'volume-mute'\n :\n (volume > 0 && volume < 0.50) ? 'volume-low'\n :\n (volume > 0.50 && volume < 0.80) ? 'volume-medium'\n : 'volume-high'\">\n </ion-icon>\n </ion-button>\n\n <ion-button fill=\"clear\" size=\"small\" slot=\"icon-only\" (click)=\"toggleFullScreen()\">\n <ion-icon name=\"expand\"></ion-icon>\n </ion-button>\n\n <ion-button fill=\"clear\" size=\"small\" slot=\"icon-only\" (click)=\"openPip()\">\n <ion-icon name=\"open\"></ion-icon>\n </ion-button>\n <!-- <ion-button size=\"small\" slot=\"icon-only\" id=\"btnStop\" class=\"\" title=\"stop\" accesskey=\"X\" (click)=\"stopVideo()\">\n <ion-icon name=\"stop\"></ion-icon>\n </ion-button>\n <ion-button size=\"small\" slot=\"icon-only\" id=\"btnReplay\" class=\"replay\" title=\"replay\" accesskey=\"R\" (click)=\"replayVideo()\">\n <ion-icon name=\"reload\"></ion-icon>\n </ion-button> -->\n </div>\n </div>\n </div>\n</div>", styles: ["#player{position:relative}#player:hover #controls{visibility:visible}.ion-video-player{width:100%}.ion-video-player video{width:inherit;height:inherit}.stop{float:right;text-align:end}ion-button{color:#fff}#controls{background-color:#0000004f;color:#fff;width:100%;position:absolute;bottom:0;padding:0 5px;box-sizing:border-box;visibility:hidden}#controls .controls-btns{display:flex;align-items:center;justify-content:space-between}#controls .controls-btns .start-stop{display:flex;align-items:center;color:#fff;font-size:10px}#controls .controls-btns .start-stop ion-button{color:#fff}progress{height:8px;width:100%;border:1.5px solid #fff;border-radius:5px}progress[value]::-moz-progress-bar{background:rgba(54,47,47,.4);border-radius:5px;box-shadow:0 2px 5px #00000040 inset}progress[value]::-webkit-progress-bar{background-color:#362f2f66;border-radius:5px;box-shadow:0 2px 5px #00000040 inset}progress[value]::-webkit-progress-value{background-color:#e74747}progress[value]::-moz-progress-value{background-color:#e74747}.volume-box{display:flex;align-items:center}.volume-box input{display:inline-block;vertical-align:middle;font-size:1em}.volume-box output{display:inline-block;vertical-align:middle;font-size:1em;background:#ff4500;padding:5px 16px;border-radius:3px;color:#fff}.volume-box .volumeRange{display:none;background-color:transparent;-webkit-appearance:none;width:50px;height:7px;background:rgba(255,255,255,.6);border-radius:5px;background-image:linear-gradient(rgb(231,71,71),rgb(231,71,71));background-repeat:no-repeat}.volume-box .volumeRange::-webkit-slider-thumb{-webkit-appearance:none;height:10px;width:10px;border-radius:50%;background:red;cursor:ew-resize;box-shadow:0 0 2px #555;-webkit-transition:background .3s ease-in-out;transition:background .3s ease-in-out}.volume-box .volumeRange::-webkit-slider-thumb:hover{background:rgb(231,71,71)}.volume-box .volumeRange::-moz-range-thumb{-webkit-appearance:none;height:10px;width:10px;border-radius:50%;background:red;cursor:ew-resize;box-shadow:0 0 2px #555;-moz-transition:background .3s ease-in-out;transition:background .3s ease-in-out}.volume-box .volumeRange::-moz-range-thumb:hover{background:rgb(231,71,71)}.volume-box .volumeRange::-ms-thumb{-webkit-appearance:none;height:10px;width:10px;border-radius:50%;background:red;cursor:ew-resize;box-shadow:0 0 2px #555;-ms-transition:background .3s ease-in-out;transition:background .3s ease-in-out}.volume-box .volumeRange::-ms-thumb:hover{background:rgb(231,71,71)}.volume-box .volumeRange::-ms-track{-webkit-appearance:none;box-shadow:none;border:none;background:transparent}.volume-box .volumeRange::-webkit-slider-runnable-track{-webkit-appearance:none;box-shadow:none;border:none;background:transparent}.volume-box .volumeRange::-moz-range-track{-webkit-appearance:none;box-shadow:none;border:none;background:transparent}.volume-box:hover .volumeRange{display:block}\n"], dependencies: [{ kind: "directive", type: i1.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "directive", type: i1.NgStyle, selector: "[ngStyle]", inputs: ["ngStyle"] }, { kind: "component", type: i2.IonButton, selector: "ion-button", inputs: ["buttonType", "color", "disabled", "download", "expand", "fill", "form", "href", "mode", "rel", "routerAnimation", "routerDirection", "shape", "size", "strong", "target", "type"] }, { kind: "component", type: i2.IonIcon, selector: "ion-icon", inputs: ["color", "flipRtl", "icon", "ios", "lazy", "md", "mode", "name", "sanitize", "size", "src"] }, { kind: "pipe", type: SecondsToHoursPipe, name: "secondsToHours" }] }); i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "15.0.1", ngImport: i0, type: IonVideoPlayerComponent, decorators: [{ type: Component, args: [{ selector: 'ion-video-player', template: "<div id=\"player\" #playerContainer class=\"ion-video-player\">\n <video id=\"video-element\" #player\n (timeupdate)=\"updateProgressBar()\"\n [poster]=\"options.poster\"\n [autoplay]=\"options.autoplay\"\n [muted]=\"options.muted\"\n (play)=\"onPlay()\"\n (pause)=\"onPause()\"\n (ended)=\"onEnded()\"\n (volumechange)=\"onVolumechange()\"\n (playing)=\"onPlaying()\"\n (error)=\"onError()\"\n (progress)=\"onProgress()\">\n <source [src]=\"options.src\" [type]=\"options.type\">\n </video>\n\n <div id=\"controls\" *ngIf=\"options.controls\">\n\n <progress id=\"progress-bar\" (click)=\"seek($event)\" min=\"0\" max=\"100\" value='1' #progressBar></progress>\n\n <div class=\"controls-btns\">\n <div class=\"start-stop\">\n <ion-button fill=\"clear\" size=\"small\" slot=\"icon-only\" class='play' (click)=\"playPauseVideo()\">\n <ion-icon [name]=\"isPlaying ? 'pause' : 'play'\"></ion-icon>\n </ion-button>\n <span *ngIf=\"player.duration\">\n {{player.currentTime | secondsToHours}} / {{player.duration | secondsToHours }}\n </span>\n </div>\n\n <div class=\"volume-box\">\n <input type=\"range\" class=\"volumeRange\"\n (change)=\"setVolume()\" \n min=\"0\"\n max=\"100\"\n step=\"1\"\n [value]=\"volumeBar.value\"\n #volumeBar\n [ngStyle]=\"{\n 'background-size': volumeBar.value + '% 100%'\n }\"\n />\n\n <ion-button fill=\"clear\" size=\"small\" slot=\"icon-only\" class=\"mute\" title=\"mute\" (click)=\"muteVolume()\">\n <ion-icon [name]=\"\n volume == 0 ? 'volume-mute'\n :\n (volume > 0 && volume < 0.50) ? 'volume-low'\n :\n (volume > 0.50 && volume < 0.80) ? 'volume-medium'\n : 'volume-high'\">\n </ion-icon>\n </ion-button>\n\n <ion-button fill=\"clear\" size=\"small\" slot=\"icon-only\" (click)=\"toggleFullScreen()\">\n <ion-icon name=\"expand\"></ion-icon>\n </ion-button>\n\n <ion-button fill=\"clear\" size=\"small\" slot=\"icon-only\" (click)=\"openPip()\">\n <ion-icon name=\"open\"></ion-icon>\n </ion-button>\n <!-- <ion-button size=\"small\" slot=\"icon-only\" id=\"btnStop\" class=\"\" title=\"stop\" accesskey=\"X\" (click)=\"stopVideo()\">\n <ion-icon name=\"stop\"></ion-icon>\n </ion-button>\n <ion-button size=\"small\" slot=\"icon-only\" id=\"btnReplay\" class=\"replay\" title=\"replay\" accesskey=\"R\" (click)=\"replayVideo()\">\n <ion-icon name=\"reload\"></ion-icon>\n </ion-button> -->\n </div>\n </div>\n </div>\n</div>", styles: ["#player{position:relative}#player:hover #controls{visibility:visible}.ion-video-player{width:100%}.ion-video-player video{width:inherit;height:inherit}.stop{float:right;text-align:end}ion-button{color:#fff}#controls{background-color:#0000004f;color:#fff;width:100%;position:absolute;bottom:0;padding:0 5px;box-sizing:border-box;visibility:hidden}#controls .controls-btns{display:flex;align-items:center;justify-content:space-between}#controls .controls-btns .start-stop{display:flex;align-items:center;color:#fff;font-size:10px}#controls .controls-btns .start-stop ion-button{color:#fff}progress{height:8px;width:100%;border:1.5px solid #fff;border-radius:5px}progress[value]::-moz-progress-bar{background:rgba(54,47,47,.4);border-radius:5px;box-shadow:0 2px 5px #00000040 inset}progress[value]::-webkit-progress-bar{background-color:#362f2f66;border-radius:5px;box-shadow:0 2px 5px #00000040 inset}progress[value]::-webkit-progress-value{background-color:#e74747}progress[value]::-moz-progress-value{background-color:#e74747}.volume-box{display:flex;align-items:center}.volume-box input{display:inline-block;vertical-align:middle;font-size:1em}.volume-box output{display:inline-block;vertical-align:middle;font-size:1em;background:#ff4500;padding:5px 16px;border-radius:3px;color:#fff}.volume-box .volumeRange{display:none;background-color:transparent;-webkit-appearance:none;width:50px;height:7px;background:rgba(255,255,255,.6);border-radius:5px;background-image:linear-gradient(rgb(231,71,71),rgb(231,71,71));background-repeat:no-repeat}.volume-box .volumeRange::-webkit-slider-thumb{-webkit-appearance:none;height:10px;width:10px;border-radius:50%;background:red;cursor:ew-resize;box-shadow:0 0 2px #555;-webkit-transition:background .3s ease-in-out;transition:background .3s ease-in-out}.volume-box .volumeRange::-webkit-slider-thumb:hover{background:rgb(231,71,71)}.volume-box .volumeRange::-moz-range-thumb{-webkit-appearance:none;height:10px;width:10px;border-radius:50%;background:red;cursor:ew-resize;box-shadow:0 0 2px #555;-moz-transition:background .3s ease-in-out;transition:background .3s ease-in-out}.volume-box .volumeRange::-moz-range-thumb:hover{background:rgb(231,71,71)}.volume-box .volumeRange::-ms-thumb{-webkit-appearance:none;height:10px;width:10px;border-radius:50%;background:red;cursor:ew-resize;box-shadow:0 0 2px #555;-ms-transition:background .3s ease-in-out;transition:background .3s ease-in-out}.volume-box .volumeRange::-ms-thumb:hover{background:rgb(231,71,71)}.volume-box .volumeRange::-ms-track{-webkit-appearance:none;box-shadow:none;border:none;background:transparent}.volume-box .volumeRange::-webkit-slider-runnable-track{-webkit-appearance:none;box-shadow:none;border:none;background:transparent}.volume-box .volumeRange::-moz-range-track{-webkit-appearance:none;box-shadow:none;border:none;background:transparent}.volume-box:hover .volumeRange{display:block}\n"] }] }], propDecorators: { playerContainer: [{ type: ViewChild, args: ['playerContainer'] }], videoPlayer: [{ type: ViewChild, args: ['player'] }], progressBar: [{ type: ViewChild, args: ['progressBar'] }], volumeBar: [{ type: ViewChild, args: ['volumeBar'] }], options: [{ type: Input }], play: [{ type: Output }], pause: [{ type: Output }], ended: [{ type: Output }], volumechange: [{ type: Output }], playing: [{ type: Output }], error: [{ type: Output }] } }); class IonVideoPlayerModule { } IonVideoPlayerModule.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "15.0.1", ngImport: i0, type: IonVideoPlayerModule, deps: [], target: i0.ɵɵFactoryTarget.NgModule }); IonVideoPlayerModule.ɵmod = i0.ɵɵngDeclareNgModule({ minVersion: "14.0.0", version: "15.0.1", ngImport: i0, type: IonVideoPlayerModule, declarations: [IonVideoPlayerComponent, SecondsToHoursPipe], imports: [CommonModule, IonicModule], exports: [IonVideoPlayerComponent, SecondsToHoursPipe] }); IonVideoPlayerModule.ɵinj = i0.ɵɵngDeclareInjector({ minVersion: "12.0.0", version: "15.0.1", ngImport: i0, type: IonVideoPlayerModule, imports: [CommonModule, IonicModule] }); i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "15.0.1", ngImport: i0, type: IonVideoPlayerModule, decorators: [{ type: NgModule, args: [{ declarations: [ IonVideoPlayerComponent, SecondsToHoursPipe ], imports: [ CommonModule, IonicModule ], exports: [ IonVideoPlayerComponent, SecondsToHoursPipe ] }] }] }); /* * Public API Surface of ion-video-player */ /** * Generated bundle index. Do not edit. */ export { IonVideoPlayerComponent, IonVideoPlayerModule, SecondsToHoursPipe }; //# sourceMappingURL=ion-video-player.mjs.map //# sourceMappingURL=ion-video-player.mjs.map