vue怎么实现歌词播放
实现歌词播放的基本思路
在Vue中实现歌词播放功能,通常需要结合音频播放器和歌词解析模块。核心是将音频当前播放时间与歌词时间轴同步,实现高亮显示当前歌词的效果。
歌词文件解析
歌词文件通常为LRC格式,需要解析时间戳和歌词内容。可以使用正则表达式将歌词文本解析为结构化数据:
function parseLrc(lrcText) {
const lines = lrcText.split('\n')
const result = []
const timeReg = /\[(\d{2}):(\d{2})\.(\d{2,3})\]/
lines.forEach(line => {
const matches = timeReg.exec(line)
if (matches) {
const min = parseInt(matches[1])
const sec = parseInt(matches[2])
const ms = parseInt(matches[3].length === 3 ? matches[3] : matches[3] * 10)
const time = min * 60 + sec + ms / 1000
const text = line.replace(timeReg, '').trim()
result.push({ time, text })
}
})
return result
}
音频播放与歌词同步
在Vue组件中,需要监听音频的timeupdate事件来更新当前歌词:
export default {
data() {
return {
audio: null,
lyrics: [],
currentLine: 0
}
},
mounted() {
this.audio = new Audio('your-audio-file.mp3')
this.audio.addEventListener('timeupdate', this.updateLyric)
// 加载歌词
this.lyrics = parseLrc(lrcText)
},
methods: {
updateLyric() {
const currentTime = this.audio.currentTime
for (let i = 0; i < this.lyrics.length; i++) {
if (currentTime < this.lyrics[i].time) {
this.currentLine = i - 1
break
}
}
}
}
}
歌词显示组件
在模板中渲染歌词列表,并高亮当前行:
<template>
<div class="lyric-container">
<ul>
<li
v-for="(line, index) in lyrics"
:key="index"
:class="{ active: index === currentLine }"
>
{{ line.text }}
</li>
</ul>
</div>
</template>
<style>
.lyric-container {
height: 300px;
overflow-y: auto;
}
.active {
color: #42b983;
font-weight: bold;
}
</style>
滚动定位优化
为了让当前歌词始终保持在可视区域中央,可以添加自动滚动功能:
methods: {
scrollToCurrent() {
const container = this.$el.querySelector('.lyric-container')
const activeItem = container.querySelector('.active')
if (activeItem) {
const containerHeight = container.clientHeight
const itemHeight = activeItem.clientHeight
const scrollTop = activeItem.offsetTop - containerHeight / 2 + itemHeight / 2
container.scrollTo({
top: scrollTop,
behavior: 'smooth'
})
}
}
}
然后在updateLyric方法中调用此方法:
updateLyric() {
// 原有逻辑...
this.scrollToCurrent()
}
歌词文件加载
可以通过API或本地文件加载歌词:
async loadLyrics() {
try {
const response = await fetch('lyrics.lrc')
const text = await response.text()
this.lyrics = parseLrc(text)
} catch (error) {
console.error('Failed to load lyrics:', error)
}
}
性能优化考虑
对于长歌词列表,可以使用虚拟滚动技术减少DOM节点数量。Vue的vue-virtual-scroller插件可以实现:
import { RecycleScroller } from 'vue-virtual-scroller'
export default {
components: { RecycleScroller },
template: `
<RecycleScroller
class="scroller"
:items="lyrics"
:item-size="32"
key-field="time"
v-slot="{ item, index }"
>
<div :class="{ active: index === currentLine }">
{{ item.text }}
</div>
</RecycleScroller>
`
}






