音频组件:播放&音量&步进&速率控制
概述
本节整合音频组件的所有控制功能:播放/暂停、音量调节、步进控制(前进/后退 15 秒)和速率控制,形成完整的播放控制面板。
综合控制逻辑实现
核心控制函数
// composables/useAudioControls.ts
import type { Howl } from 'howler'
export function useAudioControls(
audioInstance: Ref<Howl | null>,
state: AudioPlayerState
) {
// === 播放控制 ===
function play() {
if (!audioInstance.value) return
audioInstance.value.play()
state.playing = true
}
function pause() {
if (!audioInstance.value) return
audioInstance.value.pause()
state.playing = false
}
function togglePlay() {
state.playing ? pause() : play()
}
function stop() {
if (!audioInstance.value) return
audioInstance.value.stop()
state.playing = false
state.progress = 0
}
// === 进度跳转 ===
function seekTo(seconds: number) {
if (!audioInstance.value) return
audioInstance.value.seek(seconds)
state.progress = seconds
}
function seekToPercent(percent: number) {
seekTo(percent * state.duration)
}
// === 步进控制 ===
const STEP = 15 // 秒
function stepForward() {
const current = (audioInstance.value?.seek() as number) || 0
seekTo(Math.min(current + STEP, state.duration))
}
function stepBackward() {
const current = (audioInstance.value?.seek() as number) || 0
seekTo(Math.max(current - STEP, 0))
}
// === 音量控制 ===
function setVolume(val: number) {
const volume = Math.max(0, Math.min(1, val))
audioInstance.value?.volume(volume)
state.volume = volume
}
function toggleMute() {
const newMuted = !state.muted
audioInstance.value?.mute(newMuted)
state.muted = newMuted
}
// === 速率控制 ===
function setRate(val: number) {
const rate = Math.max(0.5, Math.min(4.0, val))
audioInstance.value?.rate(rate)
state.rate = rate
}
return {
play, pause, togglePlay, stop,
seekTo, seekToPercent,
stepForward, stepBackward,
setVolume, toggleMute,
setRate
}
}
typescript
播放控制按钮组件
<template>
<div class="control-buttons">
<el-button circle @click="emit('prev')" title="上一曲">
<el-icon><SkipBackward /></el-icon>
</el-button>
<el-button circle @click="emit('backward')" title="后退 15 秒">
<el-icon><Rewind /></el-icon>
</el-button>
<el-button
type="primary"
circle
size="large"
@click="emit('togglePlay')"
:title="playing ? '暂停' : '播放'"
>
<el-icon>
<VideoPause v-if="playing" />
<VideoPlay v-else />
</el-icon>
</el-button>
<el-button circle @click="emit('forward')" title="前进 15 秒">
<el-icon><FastForward /></el-icon>
</el-button>
<el-button circle @click="emit('next')" title="下一曲">
<el-icon><SkipForward /></el-icon>
</el-button>
</div>
</template>
<script setup lang="ts">
defineProps<{ playing: boolean }>()
const emit = defineEmits<{
togglePlay: []
prev: []
next: []
forward: []
backward: []
}>()
</script>
<style scoped>
.control-buttons {
display: flex;
align-items: center;
gap: 8px;
}
</style>
vue
控制面板完整组合
<template>
<div class="audio-player-panel">
<!-- 进度条 -->
<ProgressBar
v-model="progressPercent"
:duration="state.duration"
:current-time="state.progress"
/>
<!-- 控制按钮 -->
<div class="controls-row">
<!-- 循环模式 -->
<LoopControl v-model="loopMode" @change="handleLoopChange" />
<!-- 播放控制 -->
<ControlButtons
:playing="state.playing"
@toggle-play="togglePlay"
@prev="handlePrev"
@next="handleNext"
@forward="stepForward"
@backward="stepBackward"
/>
<!-- 音量 + 速率 -->
<div class="extra-controls">
<VolumeControl v-model="state.volume" :muted="state.muted" />
<RateControl v-model="state.rate" />
</div>
</div>
</div>
</template>
vue
小结
- 播放控制通过
play()/pause()/stop()实现,步进通过seek()+ 偏移量实现 - 音量范围 0-1,速率范围 0.5-4.0,均通过 Howler.js API 实时生效
- 控制逻辑可抽取为
useAudioControlscomposable,便于复用 - 按钮组件通过 emit 事件与父组件通信,保持组件职责单一
↑