diff --git a/src/app/components/analyser/Analyser.ts b/src/app/components/analyser/Analyser.ts index 9cb7909..8ee9d36 100644 --- a/src/app/components/analyser/Analyser.ts +++ b/src/app/components/analyser/Analyser.ts @@ -1,4 +1,4 @@ -import {AfterViewInit, Component, effect, ElementRef, inject, OnInit, ViewChild, viewChild} from '@angular/core'; +import {AfterViewInit, Component, effect, ElementRef, inject, ViewChild} from '@angular/core'; import {AudioService} from '../../services/audio.service'; @Component({ @@ -6,6 +6,10 @@ import {AudioService} from '../../services/audio.service'; templateUrl: 'analyser.html', }) export class Analyser implements AfterViewInit { + public readonly height = 150; + public readonly bottomOffset = 50; + public readonly offsetBuffer = 20; + public color = "rgb(80,0,80)" protected audio: AudioService = inject(AudioService); @ViewChild('analyserCanvas') canvasRef!: ElementRef; protected canvas!: HTMLCanvasElement; @@ -20,6 +24,17 @@ export class Analyser implements AfterViewInit { ngAfterViewInit(): void { this.canvas = this.canvasRef.nativeElement as HTMLCanvasElement; + this.canvas.style.height = `${this.height}px`; + this.canvas.style.top = `-${this.height}px`; + document.onmousemove = (e: MouseEvent) => { + const cursorDistancefromBottom = document.documentElement.clientHeight - (e.clientY || 0); + let offset = cursorDistancefromBottom - (this.bottomOffset + this.offsetBuffer); + if (cursorDistancefromBottom < this.bottomOffset || cursorDistancefromBottom > (this.bottomOffset + this.height + this.offsetBuffer)) { + offset = this.height; + } + this.canvas.style.height = `${offset}px`; + this.canvas.style.top = `-${offset}px`; + } } draw() { @@ -29,34 +44,20 @@ export class Analyser implements AfterViewInit { const data = this.audio.analyser.analyserData; if (!ctx) return; - ctx.fillStyle = "rgb(200 200 200)"; - ctx.fillRect(0, 0, canvas.width, canvas.height); - - ctx.lineWidth = 2; - ctx.strokeStyle = "rgb(0 0 0)"; - - ctx.beginPath(); - - const sliceWidth = canvas.width / data.length; + ctx.clearRect(0, 0, canvas.width, canvas.height); + ctx.lineWidth = 0; + ctx.fillStyle = this.color; + const sliceWidth = Math.ceil(canvas.width / data.length); let x = 0; - for (let i = 0; i < data.length; i++) { const v = data[i] / 128.0; const y = (v * canvas.height) / 2; - if (i === 0) { - ctx.moveTo(x, y); - } else { - ctx.lineTo(x, y); - } - + ctx.fillRect(x, canvas.height, sliceWidth, -y); x += sliceWidth; } - ctx.lineTo(canvas.width, canvas.height / 2); - ctx.stroke(); - requestAnimationFrame(this.draw.bind(this)); } } diff --git a/src/app/components/analyser/analyser.html b/src/app/components/analyser/analyser.html index 62301bc..c163e4d 100644 --- a/src/app/components/analyser/analyser.html +++ b/src/app/components/analyser/analyser.html @@ -1 +1 @@ - + diff --git a/src/app/pages/homepage/homepage.html b/src/app/pages/homepage/homepage.html index 0925a8a..d010be5 100644 --- a/src/app/pages/homepage/homepage.html +++ b/src/app/pages/homepage/homepage.html @@ -1,4 +1,10 @@ -Home +
+ +
+ +Home
+Home
+Home
@@ -13,10 +19,50 @@ Home @if ($index === audio.index()) { * } - {{ item.track.file.filename }} + {{ item.track.file.filename }} }
{{ audio.current()?.currentTime()}} / {{audio.current()?.duration()}} -> {{ audio.progress() * 100 }} %
- +Home
+Home
+Home
+Home
+Home
+Home
+Home
+Home
+Home
+Home
+Home
+Home
+Home
+Home
+Home
+Home
+Home
+Home
+Home
+Home
+Home
+Home
+Home
+Home
+Home
+Home
+Home
+Home
+Home
+Home
+Home
+Home
+Home
+Home
+Home
+Home
+Home
+Home
+Home
+Home
+
diff --git a/src/app/pages/homepage/homepage.ts b/src/app/pages/homepage/homepage.ts index 1dfaefc..acb66de 100644 --- a/src/app/pages/homepage/homepage.ts +++ b/src/app/pages/homepage/homepage.ts @@ -26,28 +26,32 @@ export class HomePage implements AfterViewInit{ this.input = this.rangeRef.nativeElement as HTMLInputElement; } - seek(event: Event) { - this.audio.seekPercentage(Number.parseFloat(this.input.value)); + async seek(event: Event) { + await this.audio.seekPercentage(Number.parseFloat(this.input.value)); } - play(event: Event): void { - this.audio.play(); + async play(event: Event): Promise { + await this.audio.play(); } - stop(event: Event): void { - this.audio.stop(); + async stop(event: Event): Promise { + await this.audio.stop(); } - next(event: Event): void { - this.audio.next(); + async next(event: Event): Promise { + await this.audio.next(); } - prev(event: Event): void { - this.audio.prev(); + async prev(event: Event): Promise { + await this.audio.prev(); } - pause(event: Event): void { - this.audio.pause(); + async pause(event: Event): Promise { + await this.audio.pause(); + } + + async setIndex(index: number): Promise { + await this.audio.setIndex(index); } add(event: Event): void { @@ -60,10 +64,8 @@ export class HomePage implements AfterViewInit{ )); } - remove(event: Event): void { + async remove(event: Event): Promise { const item = this.audio.current(); - if (item) { - this.audio.removeItem(item); - } + if (item) await this.audio.removeItem(item); } } diff --git a/src/app/services/audio.service.ts b/src/app/services/audio.service.ts index 869e2bd..1e93f9e 100644 --- a/src/app/services/audio.service.ts +++ b/src/app/services/audio.service.ts @@ -132,18 +132,20 @@ export class AudioService { } /** - * Start playing the track at position "index" in the playlist. + * Update current index of the playlist. + * Start playing the selected track if we were already playing a track. * Deliberately take no action if the track referenced is already the current track. * @param index */ - async playIndex(index: number): Promise { - const current = this.current(); + async setIndex(index: number): Promise { const target = this.playlist.getIndex(index); + const current = this.current(); + const wasPlaying = current?.isPlaying(); if (!target || current === target) return; await current?.stop(); this.playlist.setIndex(index); - await target.play(); + if (wasPlaying) await target.play(); } /** diff --git a/src/index.html b/src/index.html index 2bec2e0..2c46559 100644 --- a/src/index.html +++ b/src/index.html @@ -7,7 +7,7 @@ - +