Skip to content

Instantly share code, notes, and snippets.

@austbot
Last active May 24, 2016 21:36
Show Gist options
  • Save austbot/5c5dffa0025cdfe7a6451bf2007ef0d9 to your computer and use it in GitHub Desktop.
Save austbot/5c5dffa0025cdfe7a6451bf2007ef0d9 to your computer and use it in GitHub Desktop.
import {Component, ViewEncapsulation, ElementRef, Inject, EventEmitter, Output, ViewChild} from 'angular2/core';
import {Input} from 'angular2/core';
import {ChangeDetectionStrategy} from 'angular2/core';
import {DatePipe} from 'angular2/common';
import {PlayerDurationPipe} from './playerDurationPipe';
import {Observable} from 'rxjs/Observable';
import {Subject} from 'rxjs/Subject';
import {Action} from '@ngrx/store';
import {FilmStrip} from './filmStrip/filmStrip';
export interface ScrubberHoverEvent {
pixels: number;
seconds: number;
}
@Component({
changeDetection: ChangeDetectionStrategy.OnPush,
selector: 'progress-bar',
directives: [FilmStrip],
pipes: [DatePipe, PlayerDurationPipe],
host: {
'(mouseenter)': 'showScrubberHandle()',
'(mouseleave)': 'hideScrubberHandle()',
'(mousemove)': 'scrubberHoverEvent.next($event)'
},
template: `
<film-strip *ngIf="!state.isLive && state.filmStripUrl" [filmStripUrl]="state.filmStripUrl" [class.visible]="scrubberHandleVisibility" [position]="scrubberHoverEvent" [style.left]="scrubberHandlePosition | async" ></film-strip>
<div #scrubber class="scrubber" (click)="changePosition.next($event)">
<div class="scrubber-handle" [class.visible]="scrubberHandleVisibility" [style.left]="scrubberHandlePosition | async"></div>
<div class="progress-container" [style.width]="progress"></div>
<div class="buffer-container" [style.width]="buffer"></div>
</div>
<span class="remaining">{{remaining | playerDuration}}</span>
`,
styles: [
require('./progressBar.scss')
]
})
/**
* @description Manages the playback location and filmstrip.
* @class ProgressBar
*/
export class ProgressBar {
/**
* @description The amount loaded in percent
* @type {string} eg. '100%'
*/
buffer: string;
/**
* @description The amount watched or position in the media.
* @type {string} eg. '10%'
*/
progress: string;
/**
* @description The amount left to watch in miliseconds
* @type {number} eg. 10000
*/
remaining: number;
/**
* @description The Hover over the progress bar event stream, maps the raw dom event to a ScrubberHoverEvent.
* @type {Observable<ScrubberHoverEvent>}
*/
scrubberHoverEvent: Observable<any>;
/**
* @description Observes the hover event and maps it to a pixel value where the scrubber handle should be positioned.
* @type {Observable<string>}
*/
scrubberHandlePosition: Observable<string>;
/**
* @description Listens to the click on the scrubber bar and tells the component to emit the latest value from the
* scrubber hover
* @type {Observable<ScrubberHoverEvent>}
*/
changePosition: Observable<any>;
/**
* @description Internal state of the scrubber handle. TODO - LOW -> map this into an observable
* @type {boolean}
*/
scrubberHandleVisibility: boolean = false;
/**
* @description The player state input (important :)
* @type {PlayerState}
*/
@Input()
state;
/**
* @description Events coming out of this component
* @type {EventEmitter}
*/
@Output()
progressBarEvent: EventEmitter<Action> = new EventEmitter();
/**
* @description The scrubber bar element
* @type {ElementRef}
*/
@ViewChild('scrubber')
scrubber: ElementRef;
ngOnInit() {
//Listen to MouseMove
this.scrubberHoverEvent = new Subject().map((event: MouseEvent): ScrubberHoverEvent => {
//The bounded position
let pos = Math.min(Math.max(0, event.offsetX), this.scrubber.nativeElement.offsetWidth);
//The ScrubberHoverEvent
return {
seconds: (pos / this.scrubber.nativeElement.offsetWidth) * this.state.duration, //Millisecond position
pixels: pos //Pixel position on page
};
});
this.scrubberHandlePosition = this.scrubberHoverEvent
.map(
(data: ScrubberHoverEvent) => {
return `${data.pixels}px`;
}
);
//Listen to the click and grab the last value from scrubberHover.
this.changePosition = new Subject().withLatestFrom(this.scrubberHoverEvent, (click: MouseEvent, hover: ScrubberHoverEvent): ScrubberHoverEvent => {
return hover;
});
this.changePosition.subscribe((data: ScrubberHoverEvent): void => {
this.progressBarEvent.emit({type: 'seek', payload: data.seconds});
});
}
ngOnChanges() {
//When the input changes recalc the percentages.
this.buffer = `${this.state.percentLoaded}%`;
this.progress = `${this.state.percentWatched}%`;
this.remaining = this.state.duration - this.state.position;
}
showScrubberHandle() {
this.scrubberHandleVisibility = true;
}
hideScrubberHandle() {
this.scrubberHandleVisibility = false;
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment