初始化

This commit is contained in:
李琦
2026-07-31 09:05:15 +08:00
parent 2a426eebe7
commit 5f00b644cf
31 changed files with 1084 additions and 106 deletions

View File

@@ -1,30 +1,27 @@
import { ref, onUnmounted } from 'vue'
import { ref, computed, onUnmounted } from 'vue'
/**
* 背景音乐控制 composable
* 处理浏览器自动播放限制:首次用户交互后再尝试播放
* 背景音乐控制 composable(支持多曲目)
* - tracks: [{ url, name }] 播放列表
* - activeUrl: 当前选中的曲目地址
* - 处理浏览器自动播放限制:首次用户交互后再尝试播放
*/
export function useAudio(initialUrl = '') {
export function useAudio() {
const isPlaying = ref(false)
const isReady = ref(false)
const tracks = ref([]) // [{ url, name }]
const activeUrl = ref('') // 当前选中曲目 url
let audio = null
let currentUrl = initialUrl
let unlockHandler = null
const setUrl = (url) => {
currentUrl = url
if (audio) {
const wasPlaying = isPlaying.value
audio.pause()
audio.src = url
isPlaying.value = false
if (wasPlaying && url) play()
}
}
const currentName = computed(() => {
const t = tracks.value.find((t) => t.url === activeUrl.value)
return t?.name || '背景音乐'
})
const ensureAudio = () => {
if (audio) return audio
audio = new Audio(currentUrl)
audio = new Audio()
audio.loop = true
audio.volume = 0.5
audio.preload = 'auto'
@@ -34,31 +31,41 @@ export function useAudio(initialUrl = '') {
return audio
}
const tryPlay = async () => {
const playUrl = async (url) => {
if (!url) return
const a = ensureAudio()
if (a.src !== url) a.src = url
activeUrl.value = url
try {
await a.play()
isPlaying.value = true
} catch (e) {
// 被浏览器拦截,等待用户手势
isPlaying.value = false
}
}
const play = async () => {
const a = ensureAudio()
try {
await a.play()
isPlaying.value = true
} catch (e) {
isPlaying.value = false
}
// 设置播放列表与默认选中项
const setTracks = (list, active) => {
tracks.value = Array.isArray(list) ? list.slice().filter((t) => t && t.url) : []
const first = tracks.value[0]?.url || ''
const chosen = active && tracks.value.some((t) => t.url === active) ? active : first
activeUrl.value = chosen
if (audio && isPlaying.value && chosen) playUrl(chosen)
}
// 切换当前播放曲目(若正在播放则立即切换)
const setActive = (url) => {
if (!tracks.value.some((t) => t.url === url)) return
if (isPlaying.value) playUrl(url)
else activeUrl.value = url
}
const play = () => playUrl(activeUrl.value)
const pause = () => {
if (audio) audio.pause()
isPlaying.value = false
}
const toggle = () => {
if (isPlaying.value) pause()
else play()
@@ -91,5 +98,5 @@ export function useAudio(initialUrl = '') {
}
})
return { isPlaying, isReady, play, pause, toggle, tryPlay, armAutoplay, setUrl }
return { isPlaying, isReady, tracks, activeUrl, currentName, setTracks, setActive, play, pause, toggle, armAutoplay }
}