ion-video-player
Version:
HTML video player for Ionic 6 applications using angular
250 lines (243 loc) • 23.3 kB
JavaScript
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