Creating web-app player seek-bar and volume controls.

This commit is contained in:
Zoe Roux 2019-09-07 04:19:39 +02:00
parent 44c8451735
commit 3ef233a1b6
4 changed files with 185 additions and 18 deletions

View File

@ -19,7 +19,15 @@
</div>
<div class="content">
<h3>S{{this.item.seasonNumber}}:E{{this.item.episodeNumber}} - {{this.item.title}}</h3>
<mat-progress-bar color="accent"></mat-progress-bar>
<div class="seek-bar">
<div id="progress-bar">
<div id="buffered"></div>
<div id="progress"></div>
</div>
<div id="thumb"><div></div></div>
</div>
<div class="buttons">
<div class="left">
<button *ngIf="this.item.previousEpisode" mat-icon-button data-toggle="tooltip" data-placement="top" title="Previous" routerLink="/watch/{{this.item.previousEpisode}}">
@ -41,12 +49,15 @@
</div>
</div>
</button>
<div id="volume">
<button mat-icon-button data-toggle="tooltip" data-placement="top" title="Volume">
<mat-icon>volume_up</mat-icon>
<mat-slider></mat-slider>
<mat-icon>{{this.volumeIcon}}</mat-icon>
</button>
<p>{{this.minutes | number: '2.0-0'}}:{{this.seconds | number: '2.0-0'}} / --:--</p>
<mat-slider [value]="volume" (input)="changeVolume($event)"></mat-slider>
</div>
<p *ngIf="this.maxHours; else elseBlock">{{this.hours | number: '2.0-0'}}:{{this.minutes | number: '2.0-0'}}:{{this.seconds | number: '2.0-0'}} / {{this.maxHours | number: '2.0-0'}}:{{this.maxMinutes | number: '2.0-0'}}:{{this.maxSeconds | number: '2.0-0'}}</p>
<ng-template #elseBlock><p>{{this.minutes | number: '2.0-0'}}:{{this.seconds | number: '2.0-0'}} / {{this.maxMinutes | number: '2.0-0'}}:{{this.maxSeconds | number: '2.0-0'}}</p></ng-template>
</div>
<div class="right">
<button *ngIf="this.item.audios != null" mat-icon-button data-toggle="tooltip" data-placement="top" title="Select audio track">

View File

@ -70,14 +70,6 @@
display: flex;
flex-direction: column;
> mat-progress-bar
{
width: 100%;
height: 2px;
margin-top: 1rem;
margin-bottom: 1rem;
}
.buttons
{
display: flex;
@ -115,6 +107,79 @@
}
}
.seek-bar
{
width: 100%;
height: auto;
padding-top: 1rem;
padding-bottom: 1rem;
position: relative;
#progress-bar
{
width: 100%;
height: 4px;
position: relative;
background-color: rgba(255, 255, 255, .2);
transform: scaleY(.6);
#progress
{
width: 0;
height: 100%;
background-color: var(--accentColor);
position: absolute;
top: 0;
left: 0;
bottom: 0;
}
#buffered
{
width: 0;
height: 100%;
background-color: rgba(255, 255, 255, .5);
position: absolute;
top: 0;
left: 0;
bottom: 0;
}
}
#thumb
{
width: 100%;
height: 12px;
position: absolute;
left: -6px;
top: 0;
bottom: 0;
margin: auto;
opacity: 0;
> div
{
width: 12px;
height: 12px;
border-radius: 6px;
background-color: var(--accentColor);
}
}
&:hover
{
#progress-bar
{
transform: scaleY(1);
}
#thumb
{
opacity: 1;
}
}
}
#nextBtn
{
@ -173,3 +238,38 @@
}
}
}
#volume
{
display: flex;
> button
{
outline: none;
}
&:hover, &:focus-within
{
> mat-slider
{
width: 100px;
}
}
> mat-slider
{
width: 0px;
min-width: 0px;
padding: 0;
height: 40px;
overflow: hidden;
transition: width .2s cubic-bezier(0.4,0, 1, 1);
&::ng-deep > div
{
top: 19px;
left: 10px;
right: 10px;
}
}
}

View File

@ -1,8 +1,10 @@
import { Component, OnInit } from '@angular/core';
import { Component, OnInit, ViewChild } from '@angular/core';
import { WatchItem } from "../../models/watch-item";
import { ActivatedRoute } from "@angular/router";
import { DomSanitizer } from "@angular/platform-browser";
import { DomSanitizer, Title } from "@angular/platform-browser";
import { Location } from "@angular/common";
import { MatSliderChange } from "@angular/material/slider";
import { HtmlAstPath } from "@angular/compiler";
@Component({
selector: 'app-player',
@ -13,16 +15,26 @@ export class PlayerComponent implements OnInit
{
item: WatchItem;
volume: number = 100;
hours: number;
minutes: number;
seconds: number;
maxHours: number;
maxMinutes: number;
maxSeconds: number;
playIcon: string = "pause"; //Icon used by the play btn.
volumeIcon: string = "volume_up"; //Icon used by the volume btn.
fullscreenIcon: string = "fullscreen"; //Icon used by the fullscreen btn.
private player: HTMLVideoElement;
private thumb: HTMLElement;
private progress: HTMLElement;
private buffered: HTMLElement;
constructor(private route: ActivatedRoute, private sanitizer: DomSanitizer, private location: Location) { }
constructor(private route: ActivatedRoute, private sanitizer: DomSanitizer, private location: Location, private title: Title) { }
ngOnInit()
{
@ -30,20 +42,32 @@ export class PlayerComponent implements OnInit
this.route.data.subscribe((data) =>
{
this.item = data.item;
this.item.duration = 20 * 60;
if (this.player)
{
this.player.load();
this.initPlayBtn();
}
this.maxSeconds = Math.round(this.item.duration % 60);
this.maxMinutes = Math.round(this.item.duration / 60 % 60);
this.maxHours = Math.round(this.item.duration / 3600);
this.title.setTitle(this.item.showTitle + " S" + this.item.seasonNumber + ":E" + this.item.episodeNumber + " - Kyoo");
});
console.log("Init");
}
ngAfterViewInit()
{
this.player = document.getElementById("player") as HTMLVideoElement;
this.thumb = document.getElementById("thumb") as HTMLElement;
this.progress = document.getElementById("progress") as HTMLElement;
this.buffered = document.getElementById("buffered") as HTMLElement;
this.player.controls = false;
//console.log(this.player.volume * 100);
//this.volume = this.player.volume * 100;
//this.changeVolumeBtn();
this.player.onplay = () =>
{
@ -58,8 +82,18 @@ export class PlayerComponent implements OnInit
this.player.ontimeupdate = () =>
{
this.hours = Math.round(this.player.currentTime / 60 % 60);
this.seconds = Math.round(this.player.currentTime % 60);
this.minutes = Math.round(this.player.currentTime / 60);
this.thumb.style.transform = "translateX(" + (this.player.currentTime / this.item.duration * 100) + "%)";
this.progress.style.width = (this.player.currentTime / this.item.duration * 100) + "%";
};
this.player.onprogress = () =>
{
if (this.player.buffered.length > 0)
this.buffered.style.width = (this.player.buffered.end(this.player.buffered.length - 1) / this.item.duration * 100) + "%";
};
@ -83,6 +117,7 @@ export class PlayerComponent implements OnInit
ngOnDestroy()
{
document.getElementById("nav").classList.remove("d-none");
this.title.setTitle("Kyoo");
}
back()
@ -112,6 +147,26 @@ export class PlayerComponent implements OnInit
document.exitFullscreen();
}
changeVolume(event: MatSliderChange)
{
this.player.volume = event.value / 100;
this.volume = event.value;
this.changeVolumeBtn();
}
changeVolumeBtn()
{
if (this.volume == 0)
this.volumeIcon = "volume_off";
else if (this.volume < 25)
this.volumeIcon = "volume_mute";
else if (this.volume < 65)
this.volumeIcon = "volume_down";
else
this.volumeIcon = "volume_up";
}
getThumb(url: string)
{

View File

@ -9,6 +9,7 @@ export interface WatchItem
video: string;
title: string;
link: string;
duration: number;
releaseDate;
previousEpisode: string;