msr-mod/src/pages/Playroom.vue
Astrian Zheng de71db1992
feat(播放器): 添加播放进度同步功能
在播放器组件中添加了对播放进度的监听和同步功能,确保进度条与播放时间保持一致。同时,在播放队列存储中添加了`updatedCurrentTime`字段,用于更新播放时间。这些改动提升了用户体验,使播放进度控制更加直观和准确。
2025-05-25 10:38:13 +10:00

81 lines
3.3 KiB
Vue

<script setup lang="ts">
import { usePlayQueueStore } from '../stores/usePlayQueueStore'
import { artistsOrganize } from '../utils'
import gsap from 'gsap'
import { Draggable } from "gsap/Draggable"
import { onMounted } from 'vue'
import { useTemplateRef } from 'vue'
import { ref, watch } from 'vue'
const playQueueStore = usePlayQueueStore()
gsap.registerPlugin(Draggable)
const progressBarThumb = useTemplateRef('progressBarThumb')
const progressBarContainer = useTemplateRef('progressBarContainer')
const displayTimeLeft = ref(false)
onMounted(() => {
Draggable.create(progressBarThumb.value, {
type: 'x',
bounds: progressBarContainer.value,
onDrag: function() {
const thumbPosition = this.x
const containerWidth = progressBarContainer.value?.clientWidth || 0
const newTime = (thumbPosition / containerWidth) * playQueueStore.duration
playQueueStore.updatedCurrentTime = newTime
}
})
})
function timeFormatter(time: number) {
const timeInSeconds = Math.floor(time)
if (timeInSeconds < 0) { return '0:00' }
const minutes = Math.floor(timeInSeconds / 60)
const seconds = Math.floor(timeInSeconds % 60)
return `${minutes}:${seconds < 10 ? '0' : ''}${seconds}`
}
// 监听播放进度,更新进度条
watch(() => playQueueStore.currentTime, () => {
const progress = playQueueStore.currentTime / playQueueStore.duration
const containerWidth = progressBarContainer.value?.clientWidth || 0
const thumbWidth = progressBarThumb.value?.clientWidth || 0
const newPosition = (containerWidth - thumbWidth) * progress
gsap.to(progressBarThumb.value, { x: newPosition, duration: 0.1 })
})
</script>
<template>
<img class="z-0 absolute top-0 left-0 w-screen h-screen blur-2xl object-cover"
:src="playQueueStore.list[playQueueStore.currentIndex].album?.coverDeUrl"
v-if="playQueueStore.list[playQueueStore.currentIndex].album?.coverDeUrl" />
<div class="w-full flex justify-center items-center my-auto gap-12 z-10 select-none">
<div class="flex flex-col text-center w-96 gap-4">
<img :src="playQueueStore.list[playQueueStore.currentIndex].album?.coverUrl"
class="rounded-2xl shadow-2xl border border-white/20 w-96 h-96" />
<div>
<div class="text-white text-lg font-medium">{{ playQueueStore.list[playQueueStore.currentIndex].song.name }}
</div>
<div class="text-white/75 text-base">
{{ artistsOrganize(playQueueStore.list[playQueueStore.currentIndex].song.artists ?? []) }} —
{{ playQueueStore.list[playQueueStore.currentIndex].album?.name ?? '未知专辑' }}</div>
</div>
<div class="flex flex-col gap-1">
<div class="w-full p-[0.125rem] bg-white/20 rounded-full backdrop-blur-3xl">
<div class="w-full" ref="progressBarContainer">
<div class="w-2 h-2 bg-white rounded-full shadow-md" ref="progressBarThumb" />
</div>
</div>
<div class="w-full flex justify-between">
<div class="text-white/75 font-light flex-1 text-left">{{ timeFormatter(Math.floor(playQueueStore.currentTime)) }}</div>
<div class="text-white text-xs text-center">MP3</div>
<button class="text-white/75 font-light flex-1 text-right" @click="displayTimeLeft = !displayTimeLeft">{{ `${displayTimeLeft ? '-' : ''}${timeFormatter(displayTimeLeft ? Math.floor(playQueueStore.duration) - Math.floor(playQueueStore.currentTime) : playQueueStore.duration)}` }}</button>
</div>
</div>
</div>
</div>
</template>