This commit is contained in:
wvffle 2022-07-21 14:55:48 +00:00 committed by Georg Krause
parent debe024f88
commit 34610670c6
6 changed files with 47 additions and 41 deletions

View File

@ -220,13 +220,11 @@ const touchProgress = (event: MouseEvent) => {
> >
<div <div
class="buffer bar" class="buffer bar"
:data-percent="bufferProgress" :style="{ 'transform': `scaleX(${bufferProgress / 100})` }"
:style="{ 'width': bufferProgress + '%' }"
/> />
<div <div
class="position bar" class="position bar"
:data-percent="progress" :style="{ 'transform': `scaleX(${progress / 100})` }"
:style="{ 'width': progress + '%' }"
/> />
</div> </div>
</div> </div>

View File

@ -117,13 +117,11 @@ const switchTab = () => {
> >
<div <div
class="buffer bar" class="buffer bar"
:data-percent="bufferProgress" :style="{ 'transform': `scaleX(${bufferProgress / 100})` }"
:style="{ 'width': bufferProgress + '%' }"
/> />
<div <div
class="position bar" class="position bar"
:data-percent="progress" :style="{ 'transform': `scaleX(${progress / 100})` }"
:style="{ 'width': progress + '%' }"
/> />
</div> </div>
<div class="controls-row"> <div class="controls-row">

View File

@ -2,7 +2,7 @@ import type { Track } from '~/types'
import { computed, watchEffect, ref, watch } from 'vue' import { computed, watchEffect, ref, watch } from 'vue'
import { Howler } from 'howler' import { Howler } from 'howler'
import { useIntervalFn, useTimeoutFn } from '@vueuse/core' import { useRafFn, useTimeoutFn } from '@vueuse/core'
import useQueue from '~/composables/audio/useQueue' import useQueue from '~/composables/audio/useQueue'
import useSound from '~/composables/audio/useSound' import useSound from '~/composables/audio/useSound'
import toLinearVolumeScale from '~/composables/audio/toLinearVolumeScale' import toLinearVolumeScale from '~/composables/audio/toLinearVolumeScale'
@ -119,11 +119,16 @@ const progress = computed({
get: () => store.getters['player/progress'], get: () => store.getters['player/progress'],
set: (time) => { set: (time) => {
if (currentSound.value?.state() === 'loaded') { if (currentSound.value?.state() === 'loaded') {
store.state.player.currentTime = time
const duration = currentSound.value.duration() const duration = currentSound.value.duration()
currentSound.value.triggerSoundProgress(time, duration)
}
}
})
store.dispatch('player/updateProgress', time) const bufferProgress = computed(() => store.state.player.bufferProgress)
currentSound.value._triggerSoundProgress() onSoundProgress(({ node, time, duration }) => {
const toPreload = store.state.queue.tracks[currentIndex.value + 1] const toPreload = store.state.queue.tracks[currentIndex.value + 1]
if (!nextTrackPreloaded.value && toPreload && (time > PRELOAD_DELAY || duration - time < 30)) { if (!nextTrackPreloaded.value && toPreload && (time > PRELOAD_DELAY || duration - time < 30)) {
loadSound(toPreload) loadSound(toPreload)
@ -136,19 +141,14 @@ const progress = computed({
isListeningSubmitted.value = true isListeningSubmitted.value = true
} }
} }
}
}
})
const bufferProgress = computed(() => store.state.player.bufferProgress)
onSoundProgress((node: HTMLAudioElement) => {
// from https://github.com/goldfire/howler.js/issues/752#issuecomment-372083163 // from https://github.com/goldfire/howler.js/issues/752#issuecomment-372083163
const { buffered, currentTime: time } = node const { buffered, currentTime } = node
let range = 0 let range = 0
try { try {
while (buffered.start(range) >= time || time >= buffered.end(range)) { while (buffered.start(range) >= currentTime || currentTime >= buffered.end(range)) {
range += 1 range += 1
} }
} catch (IndexSizeError) { } catch (IndexSizeError) {
@ -181,11 +181,11 @@ onSoundProgress((node: HTMLAudioElement) => {
}) })
const observeProgress = ref(false) const observeProgress = ref(false)
useIntervalFn(() => { useRafFn(() => {
if (observeProgress.value && currentSound.value?.state() === 'loaded') { if (observeProgress.value && currentSound.value?.state() === 'loaded') {
progress.value = currentSound.value.seek() progress.value = currentSound.value.seek()
} }
}, 1000) })
watch(playing, async (isPlaying) => { watch(playing, async (isPlaying) => {
if (currentSound.value) { if (currentSound.value) {

View File

@ -6,7 +6,7 @@ import useTrackSources from '~/composables/audio/useTrackSources'
import useSoundCache from '~/composables/audio/useSoundCache' import useSoundCache from '~/composables/audio/useSoundCache'
import usePlayer from '~/composables/audio/usePlayer' import usePlayer from '~/composables/audio/usePlayer'
import store from '~/store' import store from '~/store'
import { createEventHook } from '@vueuse/core' import { createEventHook, useThrottleFn } from '@vueuse/core'
interface Sound { interface Sound {
id?: number id?: number
@ -18,7 +18,7 @@ interface Sound {
seek: (time?: number) => number seek: (time?: number) => number
duration: () => number duration: () => number
getSource: () => boolean getSource: () => boolean
_triggerSoundProgress: () => void triggerSoundProgress: (time: number, duration: number) => void
} }
const soundCache = useSoundCache() const soundCache = useSoundCache()
@ -28,7 +28,7 @@ const looping = computed(() => store.state.player.looping)
const currentSound = ref() const currentSound = ref()
const soundId = ref() const soundId = ref()
const soundProgress = createEventHook<HTMLAudioElement>() const soundProgress = createEventHook<{ node: HTMLAudioElement, time: number, duration: number }>()
const createSound = (howl: Howl): Sound => ({ const createSound = (howl: Howl): Sound => ({
howl, howl,
@ -46,7 +46,7 @@ const createSound = (howl: Howl): Sound => ({
seek: (time?: number) => howl.seek(time), seek: (time?: number) => howl.seek(time),
duration: () => howl.duration(), duration: () => howl.duration(),
getSource: () => (howl as any)._sounds[0], getSource: () => (howl as any)._sounds[0],
_triggerSoundProgress: () => soundProgress.trigger((howl as any)._sounds[0]._node) triggerSoundProgress: useThrottleFn((time: number, duration: number) => soundProgress.trigger({ node: (howl as any)._sounds[0]._node, time, duration }), 1000)
}) })
const loadSound = (track: Track): Sound => { const loadSound = (track: Track): Sound => {

View File

@ -37,7 +37,11 @@
} }
.ui.progress .bar { .ui.progress .bar {
transition: none; transition: transform .2s linear;
width: 100%;
transform: scaleX(0);
transform-origin: top left;
will-change: transform;
} }
.ui.progress .buffer.bar { .ui.progress .buffer.bar {
@ -72,10 +76,9 @@
animation-timing-function: linear; animation-timing-function: linear;
animation-iteration-count: infinite; animation-iteration-count: infinite;
} }
.ui.progress:not([data-percent]):not(.indeterminate) .ui.progress:not(.indeterminate)
.bar.position:not(.buffer) { .bar.position:not(.buffer) {
background: var(--vibrant-color); background: var(--vibrant-color);
min-width: 0;
} }
.track-controls { .track-controls {

View File

@ -163,15 +163,25 @@
.progress-area { .progress-area {
overflow: hidden; overflow: hidden;
} }
.progress-area .progress {
border-radius: 0.28571429rem;
}
.progress-wrapper, .warning.message { .progress-wrapper, .warning.message {
max-width: 25em; max-width: 25em;
margin: 0 auto; margin: 0 auto;
} }
.ui.progress .bar {
transition: transform .2s linear;
width: 100%;
transform: scaleX(0);
transform-origin: top left;
will-change: transform;
}
.ui.progress .buffer.bar { .ui.progress .buffer.bar {
position: absolute; position: absolute;
background-color: rgba(255, 255, 255, 0.15); background-color: rgba(255, 255, 255, 0.15);
} }
.ui.progress:not([data-percent]):not(.indeterminate) .ui.progress:not(.indeterminate)
.bar.position:not(.buffer) { .bar.position:not(.buffer) {
background: var(--vibrant-color); background: var(--vibrant-color);
} }
@ -201,9 +211,6 @@
} }
.progress { .progress {
cursor: pointer; cursor: pointer;
.bar {
min-width: 0 !important;
}
} }
.player-controls { .player-controls {