fix: volumeBar UI

This commit is contained in:
Alikia2x 2024-05-19 18:58:12 +08:00
parent 7b87a649ac
commit 65a1c26f1e
5 changed files with 115 additions and 16 deletions

View File

@ -1,6 +1,6 @@
{ {
"name": "aquavox", "name": "aquavox",
"version": "1.10.0", "version": "1.10.1",
"private": false, "private": false,
"scripts": { "scripts": {
"dev": "vite dev", "dev": "vite dev",

View File

@ -2,7 +2,7 @@
import formatDuration from '$lib/formatDuration'; import formatDuration from '$lib/formatDuration';
import { onMount } from 'svelte'; import { onMount } from 'svelte';
import userAdjustingProgress from '$lib/state/userAdjustingProgress'; import userAdjustingProgress from '$lib/state/userAdjustingProgress';
import progressBarRaw from '$lib/state/progressBarRaw'; import progressBarSlideValue from '$lib/state/progressBarSlideValue';
export let name: string; export let name: string;
export let singer: string = ''; export let singer: string = '';
@ -18,22 +18,39 @@
export let hasLyrics: boolean; export let hasLyrics: boolean;
let progressBar: HTMLDivElement; let progressBar: HTMLDivElement;
let volumeBar: HTMLInputElement; let volumeBar: HTMLDivElement;
let showInfoTop: boolean = false; let showInfoTop: boolean = false;
let isInfoTopOverflowing = false; let isInfoTopOverflowing = false;
let songInfoTopContainer: HTMLDivElement; let songInfoTopContainer: HTMLDivElement;
let songInfoTopContent: HTMLSpanElement; let songInfoTopContent: HTMLSpanElement;
let lastTouchProgress: number;
let userAdjustingVolume = false;
const mql = window.matchMedia('(max-width: 1280px)'); const mql = window.matchMedia('(max-width: 1280px)');
function volumeBarOnChange(e: any) { function volumeBarOnChange(e: MouseEvent) {
adjustVolume(e.target.value); const value = e.offsetX / volumeBar.getBoundingClientRect().width;
localStorage.setItem('volume', e.target.value); adjustVolume(value);
localStorage.setItem('volume', value.toString());
}
function volumeBarChangeTouch(e: TouchEvent) {
const value = turncate(
e.touches[0].clientX - volumeBar.getBoundingClientRect().x,
0,
volumeBar.getBoundingClientRect().width
) / volumeBar.getBoundingClientRect().width;
adjustVolume(value);
localStorage.setItem('volume', value.toString());
} }
function progressBarOnClick(e: MouseEvent) { function progressBarOnClick(e: MouseEvent) {
adjustProgress(e.offsetX / progressBar.getBoundingClientRect().width); adjustProgress(e.offsetX / progressBar.getBoundingClientRect().width);
progressBarRaw.set(e.offsetX / progressBar.getBoundingClientRect().width * duration); progressBarSlideValue.set((e.offsetX / progressBar.getBoundingClientRect().width) * duration);
}
function turncate(value: number, min: number, max: number) {
return Math.min(Math.max(value, min), max);
} }
onMount(() => { onMount(() => {
@ -94,6 +111,30 @@
adjustDisplayProgress(e.offsetX / progressBar.getBoundingClientRect().width); adjustDisplayProgress(e.offsetX / progressBar.getBoundingClientRect().width);
} }
}} }}
on:touchstart={(e) => {
if (e.cancelable) {
e.preventDefault();
}
userAdjustingProgress.set(true);
}}
on:touchmove={(e) => {
e.preventDefault();
userAdjustingProgress.set(true);
if ($userAdjustingProgress) {
lastTouchProgress =
turncate(
e.touches[0].clientX - progressBar.getBoundingClientRect().x,
0,
progressBar.getBoundingClientRect().width
) / progressBar.getBoundingClientRect().width;
adjustDisplayProgress(lastTouchProgress);
}
}}
on:touchend={(e) => {
e.preventDefault();
userAdjustingProgress.set(false);
adjustProgress(lastTouchProgress);
}}
on:mouseup={() => { on:mouseup={() => {
userAdjustingProgress.set(false); userAdjustingProgress.set(false);
}} }}
@ -127,7 +168,7 @@
</div> </div>
<div class="relative top-52 h-6 flex"> <div class="relative top-52 h-6 flex">
<img class="scale-75" src="/volumeDown.svg" alt="最小音量" /> <img class="scale-75" src="/volumeDown.svg" alt="最小音量" />
<input <!-- <input
class="mx-2 progress-bar shadow-md !translate-y-[-50%] !top-1/2" class="mx-2 progress-bar shadow-md !translate-y-[-50%] !top-1/2"
bind:this={volumeBar} bind:this={volumeBar}
on:input={volumeBarOnChange} on:input={volumeBarOnChange}
@ -136,7 +177,49 @@
max="1" max="1"
step="0.01" step="0.01"
value={$userAdjustingProgress ? volumeBar.value : volume} value={$userAdjustingProgress ? volumeBar.value : volume}
/> /> -->
<div
class="progress-bar shadow-md !top-1/2 !translate-y-[-50%]"
on:click={(e) => volumeBarOnChange(e)}
bind:this={volumeBar}
on:mousedown={() => {
userAdjustingVolume = true;
}}
on:mousemove={(e) => {
if (userAdjustingVolume) {
volumeBarOnChange(e);
}
}}
on:touchstart={(e) => {
if (e.cancelable) {
e.preventDefault();
}
userAdjustingVolume = true;
}}
on:touchmove={(e) => {
e.preventDefault();
userAdjustingVolume = true;
if (userAdjustingVolume) {
volumeBarChangeTouch(e);
}
}}
on:touchend={(e) => {
e.preventDefault();
userAdjustingVolume = false;
}}
on:mouseup={() => {
userAdjustingVolume = false;
}}
role="slider"
aria-valuemin="0"
aria-valuemax="1"
aria-valuenow={volume}
tabindex="0"
on:keydown
on:keyup
>
<div class="bar" style={`width: ${volume * 100}%;`}></div>
</div>
<img class="scale-75" src="/volumeUp.svg" alt="最大音量" /> <img class="scale-75" src="/volumeUp.svg" alt="最大音量" />
</div> </div>
</div> </div>

View File

@ -3,6 +3,7 @@
import createLyricsSearcher from '$lib/lyrics/lyricSearcher'; import createLyricsSearcher from '$lib/lyrics/lyricSearcher';
import progressBarRaw from '$lib/state/progressBarRaw'; import progressBarRaw from '$lib/state/progressBarRaw';
import type { LrcJsonData } from 'lrc-parser-ts'; import type { LrcJsonData } from 'lrc-parser-ts';
import progressBarSlideValue from '$lib/state/progressBarSlideValue';
export let lyrics: string[]; export let lyrics: string[];
export let originalLyrics: LrcJsonData; export let originalLyrics: LrcJsonData;
export let progress: number; export let progress: number;
@ -15,6 +16,7 @@
let lyricsContainer: HTMLDivElement; let lyricsContainer: HTMLDivElement;
let nextUpdate = -1; let nextUpdate = -1;
let lastAdjustProgress = 0; let lastAdjustProgress = 0;
let localProgress = 0;
let refs: HTMLParagraphElement[] = []; let refs: HTMLParagraphElement[] = [];
let _refs: any[] = []; let _refs: any[] = [];
@ -94,7 +96,6 @@
const scripts = originalLyrics.scripts; const scripts = originalLyrics.scripts;
if (!scripts) return; if (!scripts) return;
if (v) { if (v) {
console.log('!');
for (let i = 0; i < scripts.length; i++) { for (let i = 0; i < scripts.length; i++) {
refs[i].style.filter = `blur(0px)`; refs[i].style.filter = `blur(0px)`;
} }
@ -109,10 +110,20 @@
} }
}); });
// progressBarRaw is used to detect progress changes at system-level (not in AquaVox)
progressBarRaw.subscribe((progress: number) => { progressBarRaw.subscribe((progress: number) => {
if ($userAdjustingProgress === false && getLyricIndex) { if ($userAdjustingProgress === false && getLyricIndex) {
if (Math.abs(localProgress - progress) > 0.6) {
const currentLyric = refs[getLyricIndex(progress)]; const currentLyric = refs[getLyricIndex(progress)];
b(currentLyric); b(currentLyric);
}
localProgress = progress;
}
});
// progressBarSlideValue is to detect progress bar sliding event
progressBarSlideValue.subscribe((_) => {
if ($userAdjustingProgress === false && getLyricIndex) {
lastAdjustProgress = currentPositionIndex; lastAdjustProgress = currentPositionIndex;
} }
}); });
@ -121,7 +132,7 @@
if ($userAdjustingProgress) { if ($userAdjustingProgress) {
nextUpdate = progress; nextUpdate = progress;
} else { } else {
if (0 < nextUpdate - progress && nextUpdate - progress < 0.05) { if (nextUpdate - progress < 0.05) {
if ( if (
currentPositionIndex >= 0 && currentPositionIndex >= 0 &&
currentPositionIndex !== currentAnimationIndex && currentPositionIndex !== currentAnimationIndex &&
@ -163,9 +174,11 @@
bind:this={lyricsContainer} bind:this={lyricsContainer}
> >
{#if debugMode} {#if debugMode}
<p class="fixed top-6 right-20"> <p class="fixed top-6 right-20 font-mono text-sm">
LyricIndex: {currentLyricIndex} PositionIndex: {currentPositionIndex} AnimationIndex:{currentAnimationIndex} LyricIndex: {currentLyricIndex} PositionIndex: {currentPositionIndex} AnimationIndex:{currentAnimationIndex}
NextUpdate: {Math.floor(nextUpdate / 60)}m {Math.round((nextUpdate % 60) * 100) / 100}s NextUpdate: {nextUpdate}
Progress: {progress.toFixed(2)}
lastAdjustProgress: {lastAdjustProgress}
</p> </p>
{/if} {/if}
{#each lyrics as lyric, i} {#each lyrics as lyric, i}

View File

@ -0,0 +1,3 @@
import { writable } from 'svelte/store';
const progressBarSlideValue = writable(0);
export default progressBarSlideValue;

View File

@ -77,7 +77,7 @@
</ul> </ul>
</div> </div>
<p> <p>
AquaVox 1.10.0 · 早期公开预览 · 源代码参见 AquaVox 1.10.1 · 早期公开预览 · 源代码参见
<a href="https://github.com/alikia2x/aquavox">GitHub</a> <a href="https://github.com/alikia2x/aquavox">GitHub</a>
</p> </p>
<a href="/import">导入音乐</a> <br /> <a href="/import">导入音乐</a> <br />