初始化
This commit is contained in:
@@ -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 }
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user