🪝 Composables 组合式函数
🎧 useAudio
音频播放控制的核心组合式函数,封装了播放器的所有操作。
📁 文件位置:src/composables/useAudio.ts
📤 返回值
📊 状态
| 属性 | 类型 | 说明 |
|---|---|---|
currentSong | ComputedRef<Song | null> | 当前播放歌曲 |
isPlaying | ComputedRef<boolean> | 是否正在播放 |
isLoading | ComputedRef<boolean> | 是否加载中 |
playlist | ComputedRef<Song[]> | 播放列表 |
playMode | ComputedRef<PlayMode> | 播放模式 |
volume | ComputedRef<number> | 音量 (0-1) |
currentTime | ComputedRef<number> | 当前播放时间(秒) |
duration | ComputedRef<number> | 歌曲总时长(秒) |
progress | ComputedRef<number> | 播放进度 (0-100) |
hasNext | ComputedRef<boolean> | 是否有下一首 |
hasPrevious | ComputedRef<boolean> | 是否有上一首 |
formattedCurrentTime | ComputedRef<string> | 格式化当前时间 mm:ss |
formattedDuration | ComputedRef<string> | 格式化总时长 mm:ss |
playModeText | ComputedRef<string> | 播放模式文本 |
playModeIcon | ComputedRef<string> | 播放模式图标类名 |
▶️ 播放控制
| 方法 | 参数 | 说明 |
|---|---|---|
play(song?, index?) | Song, number | 播放指定歌曲 |
pause() | - | 暂停播放 |
resume() | - | 继续播放 |
togglePlay() | - | 切换播放/暂停 |
next() | - | 下一首 |
previous() | - | 上一首 |
stop() | - | 停止播放 |
🔁 播放模式
| 方法 | 参数 | 说明 |
|---|---|---|
togglePlayMode() | - | 循环切换播放模式 |
setPlayMode(mode) | PlayMode | 设置指定播放模式 |
🔊 音量控制
| 方法 | 参数 | 说明 |
|---|---|---|
setVolume(vol) | number (0-1) | 设置音量 |
toggleMute() | - | 切换静音 |
⏱️ 进度控制
| 方法 | 参数 | 说明 |
|---|---|---|
setProgress(prog) | number (0-100) | 设置播放进度百分比 |
setCurrentTime(time) | number | 设置播放时间(秒) |
📋 播放列表管理
| 方法 | 参数 | 说明 |
|---|---|---|
addSong(song) | Song | 添加歌曲到列表 |
addSongs(songs) | Song[] | 批量添加歌曲 |
removeSong(id) | string | number | 移除歌曲 |
removeSongs(ids) | Array<string | number> | 批量移除 |
clearPlaylist() | - | 清空播放列表 |
setPlaylist(songs, startIndex?) | Song[], number | 设置播放列表 |
playByIndex(index) | number | 播放指定索引歌曲 |
moveSong(from, to) | number, number | 移动歌曲位置 |
queueNext(id) | string | number | 添加到下一首播放 |
🔧 其他
| 方法 | 说明 |
|---|---|
clearHistory() | 清空播放历史 |
clearError() | 清除错误信息 |
handleKeyboard(event) | 处理键盘事件 |
setupMediaSession() | 设置系统媒体控制 |
💡 使用示例
vue
<script setup lang="ts">
import { useAudio } from '@/composables/useAudio'
const {
currentSong,
isPlaying,
progress,
formattedCurrentTime,
formattedDuration,
togglePlay,
next,
previous,
setProgress,
} = useAudio()
</script>
<template>
<div class="player">
<div v-if="currentSong">
<img :src="currentSong.cover" />
<span>{{ currentSong.name }} - {{ currentSong.artist }}</span>
</div>
<div class="controls">
<button @click="previous">上一首</button>
<button @click="togglePlay">
{{ isPlaying ? '暂停' : '播放' }}
</button>
<button @click="next">下一首</button>
</div>
<div class="progress">
<span>{{ formattedCurrentTime }}</span>
<input
type="range"
:value="progress"
@input="setProgress($event.target.value)"
/>
<span>{{ formattedDuration }}</span>
</div>
</div>
</template>📝 useLyrics
歌词解析与同步的组合式函数。
📁 文件位置:src/composables/useLyrics.ts
📘 类型定义
ts
interface LyricLine {
time: number // 时间戳(秒)
ori: string // 原文歌词
tran?: string // 翻译歌词
roma?: string // 罗马音
}📤 返回值
| 属性/方法 | 类型 | 说明 |
|---|---|---|
lyricsOriginal | Ref<RawLyricLine[]> | 原始歌词数组 |
lyricsTrans | Ref<RawLyricLine[]> | 翻译歌词数组 |
lyricsRoma | Ref<RawLyricLine[]> | 罗马音数组 |
showTrans | Ref<boolean> | 是否显示翻译 |
showRoma | Ref<boolean> | 是否显示罗马音 |
mergedLines | ComputedRef<LyricLine[]> | 合并后的歌词行 |
activeSingleLyrics | ComputedRef<LyricLine[]> | 活动歌词列表 |
activeTimeline | ComputedRef<number[]> | 时间轴数组 |
loading | Ref<boolean> | 是否加载中 |
fetchLyrics(id, force?) | Function | 获取歌词 |
timeForIndex(index) | Function | 获取指定索引的时间 |
💡 使用示例
vue
<script setup lang="ts">
import { useLyrics } from '@/composables/useLyrics'
import { useAudio } from '@/composables/useAudio'
const { activeSingleLyrics, fetchLyrics, loading } = useLyrics()
const { currentSong, currentTime } = useAudio()
watch(() => currentSong.value?.id, (id) => {
if (id) fetchLyrics(id)
})
const currentLineIndex = computed(() => {
const time = currentTime.value
let idx = 0
for (let i = 0; i < activeSingleLyrics.value.length; i++) {
if (activeSingleLyrics.value[i].time <= time) idx = i
else break
}
return idx
})
</script>
<template>
<div class="lyrics">
<div v-if="loading">加载中...</div>
<div
v-for="(line, i) in activeSingleLyrics"
:key="i"
:class="{ active: i === currentLineIndex }"
>
<p class="ori">{{ line.ori }}</p>
<p v-if="line.tran" class="tran">{{ line.tran }}</p>
</div>
</div>
</template>⌨️ useGlobalKeyboard
全局键盘快捷键支持。
📁 文件位置:src/composables/useAudio.ts
📤 返回值
| 方法 | 说明 |
|---|---|
enableGlobalKeyboard() | 启用全局键盘监听 |
disableGlobalKeyboard() | 禁用全局键盘监听 |
💡 使用示例
vue
<script setup lang="ts">
import { useGlobalKeyboard } from '@/composables/useAudio'
const { enableGlobalKeyboard, disableGlobalKeyboard } = useGlobalKeyboard()
onMounted(() => {
enableGlobalKeyboard()
})
onUnmounted(() => {
disableGlobalKeyboard()
})
</script>🎹 支持的快捷键
| 按键 | 功能 |
|---|---|
Space | 播放/暂停 |
ArrowLeft | 快退 10 秒 |
ArrowRight | 快进 10 秒 |
Ctrl + ArrowLeft | 上一首 |
Ctrl + ArrowRight | 下一首 |
ArrowUp | 音量 +10% |
ArrowDown | 音量 -10% |
M | 静音切换 |
R | 切换播放模式 |