feat(Player): 添加媒体会话元数据和播放控制功能
为播放器组件添加了媒体会话元数据设置功能,包括歌曲标题、艺术家、专辑和封面信息。同时实现了上一曲和下一曲的播放控制逻辑,并优化了音频元素的交互事件处理。
This commit is contained in:
parent
6743b694c8
commit
2ffa445413
|
@ -7,17 +7,69 @@ const playQueueStore = usePlayQueueStore()
|
||||||
const player = useTemplateRef('playerRef')
|
const player = useTemplateRef('playerRef')
|
||||||
|
|
||||||
watch(() => playQueueStore.isPlaying, (newValue) => {
|
watch(() => playQueueStore.isPlaying, (newValue) => {
|
||||||
if (newValue) { player.value?.play() }
|
if (newValue) {
|
||||||
|
player.value?.play()
|
||||||
|
setMetadata()
|
||||||
|
}
|
||||||
else { player.value?.pause() }
|
else { player.value?.pause() }
|
||||||
})
|
})
|
||||||
|
|
||||||
|
watch(() => playQueueStore.currentIndex, () => {
|
||||||
|
setMetadata()
|
||||||
|
})
|
||||||
|
|
||||||
|
function artistsOrganize(list: string[]) {
|
||||||
|
if (list.length === 0) { return '未知音乐人' }
|
||||||
|
return list.map((artist) => {
|
||||||
|
return artist
|
||||||
|
}).join(' / ')
|
||||||
|
}
|
||||||
|
|
||||||
|
function setMetadata() {
|
||||||
|
if ('mediaSession' in navigator) {
|
||||||
|
navigator.mediaSession.metadata = new MediaMetadata({
|
||||||
|
title: playQueueStore.list[playQueueStore.currentIndex].song.name,
|
||||||
|
artist: artistsOrganize(playQueueStore.list[playQueueStore.currentIndex].song.artists ?? []),
|
||||||
|
album: playQueueStore.list[playQueueStore.currentIndex].album?.name,
|
||||||
|
artwork: [
|
||||||
|
{ src: playQueueStore.list[playQueueStore.currentIndex].album?.coverUrl ?? '', sizes: '500x500', type: 'image/png' },
|
||||||
|
]
|
||||||
|
})
|
||||||
|
|
||||||
|
navigator.mediaSession.setActionHandler('previoustrack', playPrevious)
|
||||||
|
navigator.mediaSession.setActionHandler('nexttrack', playNext)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function playNext() {
|
||||||
|
if (playQueueStore.currentIndex === playQueueStore.list.length - 1) {
|
||||||
|
playQueueStore.currentIndex = 0
|
||||||
|
player.value?.pause()
|
||||||
|
} else {
|
||||||
|
playQueueStore.currentIndex++
|
||||||
|
player.value?.play()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function playPrevious() {
|
||||||
|
if (player.value && (player.value.currentTime ?? 0) < 5 && playQueueStore.currentIndex > 0) {
|
||||||
|
playQueueStore.currentIndex--
|
||||||
|
player.value?.play()
|
||||||
|
} else {
|
||||||
|
if (player.value) { player.value.currentTime = 0 }
|
||||||
|
}
|
||||||
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
<div>
|
<div>
|
||||||
<audio :src="playQueueStore.list[playQueueStore.currentIndex] ? playQueueStore.list[playQueueStore.currentIndex].song.sourceUrl : ''" ref="playerRef" autoplay v-if="playQueueStore.list.length !== 0"></audio>
|
<audio
|
||||||
|
:src="playQueueStore.list[playQueueStore.currentIndex] ? playQueueStore.list[playQueueStore.currentIndex].song.sourceUrl : ''"
|
||||||
|
ref="playerRef" autoplay v-if="playQueueStore.list.length !== 0" @ended="playNext" @pause="playQueueStore.isPlaying = false" @play="playQueueStore.isPlaying = true">
|
||||||
|
</audio>
|
||||||
|
|
||||||
<div
|
<div
|
||||||
class="text-white w-48 h-9 bg-neutral-800/80 border border-[#ffffff39] rounded-full text-center backdrop-blur-3xl flex gap-2 overflow-hidden"
|
class="text-white w-48 h-9 bg-neutral-800/80 border border-[#ffffff39] rounded-full text-center backdrop-blur-3xl flex gap-2 overflow-hidden select-none"
|
||||||
v-if="playQueueStore.list.length !== 0">
|
v-if="playQueueStore.list.length !== 0">
|
||||||
<img :src="playQueueStore.list[playQueueStore.currentIndex].album?.coverUrl ?? ''" class="rounded-full" />
|
<img :src="playQueueStore.list[playQueueStore.currentIndex].album?.coverUrl ?? ''" class="rounded-full" />
|
||||||
<div class="flex-1 flex items-center">
|
<div class="flex-1 flex items-center">
|
||||||
|
|
Loading…
Reference in New Issue
Block a user