io-player
Version:
IoPlayer - Audio Player web component
1 lines • 13.9 kB
Source Map (JSON)
{"version":3,"file":"io-player.mjs","sources":["../../src/app/io-player/io-player/io-player.service.ts","../../src/app/io-player/io-player/io-player.component.ts","../../src/app/io-player/io-player/io-player.component.html","../../src/app/io-player/io-player.module.ts","../../src/io-player.ts"],"sourcesContent":["import {Injectable, OnDestroy} from '@angular/core';\nimport {BehaviorSubject, from, fromEvent, Observable, Subscription} from 'rxjs';\nimport {map} from 'rxjs/operators';\n\n\n@Injectable()\nexport class IoPlayerService implements OnDestroy {\n\n private _audio: HTMLAudioElement;\n private _isPlaying = false;\n private _isPlaying$: BehaviorSubject<boolean>;\n private subscriptions: Subscription[] = [];\n\n constructor() {\n this._isPlaying$ = new BehaviorSubject(this._isPlaying);\n }\n\n\n ngOnDestroy() {\n if (this._isPlaying) {\n this.pause();\n }\n this.subscriptions.forEach(subscription => subscription.unsubscribe());\n }\n\n /**\n * @description initiatize audio player.\n */\n init(source: string) {\n this._audio = document.createElement('audio');\n this._audio.src = source;\n this.audioFinish$.subscribe(() => this.pause());\n }\n\n /**\n * @description API to play current player.\n */\n play() {\n if (!this._isPlaying) {\n from(this._audio.play()).subscribe(() => {\n this.toggleIsPlaying();\n });\n }\n }\n\n /**\n * @description API to pause player.\n */\n pause() {\n if (!this._isPlaying) return;\n this._audio.pause();\n this.toggleIsPlaying();\n }\n\n forward(offset = 10.0) {\n if (!this._isPlaying) return;\n this._audio.currentTime += offset;\n }\n\n backward(offset = 10.0) {\n if (!this._isPlaying) return;\n this._audio.currentTime -= offset;\n }\n\n /**\n * @description ask for specific pourcentage position.\n */\n readFromPercentage(percentage: number) {\n this._audio.currentTime = this._audio.duration * percentage / 100;\n }\n\n /**\n * @description switch isPlaying state.\n */\n private toggleIsPlaying() {\n this._isPlaying = !this._isPlaying;\n this._isPlaying$.next(this._isPlaying);\n }\n\n /**\n * @description observable of current percentage position in audio.\n */\n get percentageReaded$(): Observable<number> {\n return fromEvent(this._audio, 'timeupdate').pipe(map(() => {\n return (this._audio.currentTime / this._audio.duration) * 100;\n }));\n }\n\n /**\n * @description observable who notify when 'ended' audio event is fire.\n */\n get audioFinish$(): Observable<void> {\n return fromEvent(this._audio, 'ended').pipe(map(() => {\n return null;\n }));\n }\n\n /**\n * @description Observable to determine if current sound is playing or not.\n */\n get isPlaying$(): Observable<boolean> {\n return this._isPlaying$.asObservable();\n }\n}\n","import {\n ChangeDetectionStrategy, ChangeDetectorRef, Component, ElementRef, EventEmitter, Input, OnDestroy, OnInit, Output,\n ViewChild\n} from '@angular/core';\nimport {Subscription} from 'rxjs/internal/Subscription';\nimport {IoPlayerService} from './io-player.service';\n\n@Component({\n selector: 'io-player',\n templateUrl: './io-player.component.html',\n styleUrls: ['./io-player.component.scss'],\n providers: [IoPlayerService],\n changeDetection: ChangeDetectionStrategy.OnPush\n})\nexport class IoPlayerComponent implements OnInit, OnDestroy {\n @Input() src: string;\n @Input() cover: string;\n @Input() author: string;\n @Input() song: string;\n\n @Input() set fastForward(step:string) {\n this.forwardOffsetStep = parseFloat(step);\n }\n\n // eslint-disable-next-line @angular-eslint/no-output-rename\n @Output('progression') progression$: EventEmitter<number>;\n\n @ViewChild('coverEl') coverElement: ElementRef;\n @ViewChild('timelineBar') timelineElement: ElementRef;\n\n public isPlaying = false;\n public progression = 0;\n public forwardOffsetStep: number = 10.0;\n private subscriptions: Subscription[] = [];\n\n constructor(\n public playerService: IoPlayerService,\n private changeRef: ChangeDetectorRef\n ) {\n this.progression$ = new EventEmitter<number>();\n }\n\n ngOnInit() {\n this.playerService.init(this.src);\n this.subscriptions.push(\n this.playerService.isPlaying$.subscribe(state => {\n this.isPlaying = state;\n this.changeRef.detectChanges();\n }),\n this.playerService.percentageReaded$.subscribe(state => {\n this.progression = state;\n this.progression$.emit(state);\n this.changeRef.detectChanges();\n })\n );\n }\n\n ngOnDestroy() {\n this.subscriptions.forEach(subscription => subscription.unsubscribe());\n }\n\n /**\n * Click handler on play pause button.\n */\n onPlayHandler() {\n if (!this.isPlaying) {\n this.playerService.play();\n } else {\n this.playerService.pause();\n }\n }\n\n /**\n * Click Handler on timeline bar\n */\n onChangeTimelinekHandler($event: MouseEvent) {\n const percentage = Math.floor(($event.offsetX / this.timelineElement.nativeElement.offsetWidth) * 100);\n this.playerService.readFromPercentage(percentage);\n }\n\n onFastBackwardHandler() {\n this.playerService.backward(this.forwardOffsetStep);\n }\n onFastForwardHandler() {\n this.playerService.forward(this.forwardOffsetStep);\n }\n}\n","<div class=\"player\" [ngClass]=\"{play: isPlaying}\">\n <div class=\"player__bar\">\n <div class=\"player__album\">\n <div class=\"player__scale-wrapper\" [ngClass]=\"{'isPlaying': isPlaying}\">\n <div class=\"player__albumImg active-song\" #coverEl [ngStyle]=\"{backgroundImage: 'url('+cover+')'}\">\n </div>\n </div>\n </div>\n <div class=\"player__controls\">\n <div class=\"player__prev\" (click)=\"onFastBackwardHandler()\">\n <svg class=\"icon\" xmlns=\"http://www.w3.org/2000/svg\" viewBox=\"0 0 100 100\"><path d=\"M26.695 34.434v31.132L54.5 49.998z\"/><path d=\"M24.07 34.434v31.132c0 2.018 2.222 3.234 3.95 2.267l27.804-15.568c1.706-.955 1.707-3.578 0-4.533L28.02 32.168c-2.957-1.655-5.604 2.88-2.649 4.533l27.805 15.564v-4.533L25.371 63.3l3.95 2.267V34.435c-.001-3.387-5.251-3.387-5.251-.001z\"/><g><path d=\"M55.5 34.434v31.132l27.805-15.568z\"/><path d=\"M52.875 34.434v31.132c0 2.018 2.222 3.234 3.949 2.267 9.27-5.189 18.537-10.379 27.805-15.568 1.705-.955 1.705-3.578 0-4.533L56.824 32.168c-2.957-1.655-5.604 2.88-2.648 4.533l27.803 15.564v-4.533L54.176 63.3l3.949 2.267V34.435c0-3.387-5.25-3.387-5.25-.001z\"/></g></svg>\n </div>\n\n <div class=\"player__play\" (click)=\"onPlayHandler()\">\n <svg class=\"icon play\" xmlns=\"http://www.w3.org/2000/svg\" viewBox=\"0 0 64 64\"><path d=\"M51.109 30.335l-36-24A2 2 0 0 0 12 8v48a2.003 2.003 0 0 0 2 2c.388 0 .775-.113 1.109-.336l36-24a2 2 0 0 0 0-3.329z\"/></svg>\n <svg class=\"icon pause\" xmlns=\"http://www.w3.org/2000/svg\" viewBox=\"0 0 100 100\"><path d=\"M22.537 8.046h17.791c1.104 0 2.003.898 2.003 1.993v79.912a2.005 2.005 0 0 1-2.003 2.003h-17.79a2.005 2.005 0 0 1-2.003-2.003V10.04c0-1.095.898-1.993 2.002-1.993zM59.672 8.046h17.8c1.095 0 1.993.898 1.993 1.993v79.912a2.003 2.003 0 0 1-1.993 2.003h-17.8a1.997 1.997 0 0 1-1.993-2.003V10.04c0-1.095.889-1.993 1.993-1.993z\"/></svg>\n </div>\n\n <div class=\"player__next\" (click)=\"onFastForwardHandler()\">\n <svg class=\"icon\" xmlns=\"http://www.w3.org/2000/svg\" viewBox=\"0 0 100 100\"><path d=\"M26.695 34.434v31.132L54.5 49.998z\"/><path d=\"M24.07 34.434v31.132c0 2.018 2.222 3.234 3.95 2.267l27.804-15.568c1.706-.955 1.707-3.578 0-4.533L28.02 32.168c-2.957-1.655-5.604 2.88-2.649 4.533l27.805 15.564v-4.533L25.371 63.3l3.95 2.267V34.435c-.001-3.387-5.251-3.387-5.251-.001z\"/><g><path d=\"M55.5 34.434v31.132l27.805-15.568z\"/><path d=\"M52.875 34.434v31.132c0 2.018 2.222 3.234 3.949 2.267 9.27-5.189 18.537-10.379 27.805-15.568 1.705-.955 1.705-3.578 0-4.533L56.824 32.168c-2.957-1.655-5.604 2.88-2.648 4.533l27.803 15.564v-4.533L54.176 63.3l3.949 2.267V34.435c0-3.387-5.25-3.387-5.25-.001z\"/></g></svg>\n </div>\n </div>\n </div>\n <div class=\"player__timeline\">\n <p class=\"player__author\">\n {{ author }}\n </p>\n <p class=\"player__song\">\n {{ song }}\n </p>\n\n <button class=\"player__timelineHit\" (click)=\"onChangeTimelinekHandler($event)\">\n <div class=\"player__timelineBar\" #timelineBar>\n <div id=\"playhead\" [ngStyle]=\"{width: progression+'%'}\"></div>\n </div>\n </button>\n </div>\n</div>\n","import {IoPlayerComponent} from './io-player/io-player.component';\nimport {BrowserModule} from '@angular/platform-browser';\nimport {DoBootstrap, Injector, NgModule} from '@angular/core';\nimport {createCustomElement} from '@angular/elements';\n\n@NgModule({\n declarations: [\n IoPlayerComponent\n ],\n entryComponents: [\n IoPlayerComponent\n ],\n imports: [\n BrowserModule\n ],\n exports: [\n IoPlayerComponent\n ],\n providers: [],\n bootstrap: []\n})\nexport class IoPlayerModule implements DoBootstrap {\n constructor(private injector: Injector) {\n const customElement = createCustomElement(IoPlayerComponent, {injector});\n customElements.define('io-player', customElement);\n }\n\n // eslint-disable-next-line @angular-eslint/no-empty-lifecycle-method\n ngDoBootstrap() {\n }\n}\n","/**\n * Generated bundle index. Do not edit.\n */\n\nexport * from './public_api';\n"],"names":[],"mappings":"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"}