vue怎么实现歌词滚动
实现歌词滚动的基本思路
在Vue中实现歌词滚动功能,通常需要结合音频播放器和歌词解析。歌词滚动效果可以通过监听音频播放时间,动态高亮当前播放的歌词行并平滑滚动到可视区域。
解析歌词文件
歌词文件通常是LRC格式,需要解析为结构化数据。可以使用正则表达式拆分时间戳和歌词内容:
function parseLrc(lrcText) {
const lines = lrcText.split('\n')
const result = []
const timeRegex = /\[(\d{2}):(\d{2})\.(\d{2,3})\]/
lines.forEach(line => {
const matches = timeRegex.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(timeRegex, '').trim()
result.push({ time, text })
}
})
return result
}
组件结构与数据
<template>
<div class="lyric-container">
<div class="lyric-wrapper" ref="lyricWrapper">
<div
v-for="(line, index) in lyricLines"
:key="index"
:class="{ active: currentLineIndex === index }"
class="lyric-line"
>
{{ line.text }}
</div>
</div>
</div>
</template>
<script>
export default {
props: {
currentTime: Number, // 音频当前播放时间
lrcText: String // 原始歌词文本
},
data() {
return {
lyricLines: [],
currentLineIndex: 0
}
},
watch: {
lrcText: {
immediate: true,
handler(val) {
this.lyricLines = parseLrc(val)
}
}
}
}
</script>
监听播放时间更新
在组件中添加计算当前歌词行的逻辑:
export default {
// ...
watch: {
currentTime(newTime) {
if (!this.lyricLines.length) return
// 找到最后一个时间小于当前时间的歌词行
for (let i = 0; i < this.lyricLines.length; i++) {
if (this.lyricLines[i].time > newTime) {
this.currentLineIndex = i - 1
this.scrollToCurrentLine()
break
}
}
}
},
methods: {
scrollToCurrentLine() {
const wrapper = this.$refs.lyricWrapper
const activeLine = wrapper.querySelector('.active')
if (activeLine) {
const wrapperHeight = wrapper.clientHeight
const lineHeight = activeLine.clientHeight
const scrollTop = activeLine.offsetTop - wrapperHeight / 2 + lineHeight / 2
wrapper.scrollTo({
top: scrollTop,
behavior: 'smooth'
})
}
}
}
}
样式优化
添加CSS样式使歌词显示更美观:
.lyric-container {
height: 300px;
overflow: hidden;
text-align: center;
}
.lyric-wrapper {
height: 100%;
overflow-y: auto;
scroll-behavior: smooth;
}
.lyric-line {
padding: 8px 0;
transition: all 0.3s ease;
opacity: 0.6;
}
.lyric-line.active {
font-size: 1.2em;
opacity: 1;
color: #42b983; /* Vue主题色 */
}
与音频播放器集成
在实际应用中,需要将歌词组件与音频播放器组件结合使用:
<template>
<div>
<audio-player @timeupdate="handleTimeUpdate" />
<lyric-display :current-time="currentTime" :lrc-text="lrcText" />
</div>
</template>
<script>
export default {
data() {
return {
currentTime: 0,
lrcText: '' // 从API或文件加载歌词
}
},
methods: {
handleTimeUpdate(time) {
this.currentTime = time
}
}
}
</script>
性能优化建议
对于长歌词列表,可以使用虚拟滚动技术减少DOM节点数量。当歌词行数超过100时,考虑使用vue-virtual-scroller等库优化性能。
import { RecycleScroller } from 'vue-virtual-scroller'
export default {
components: {
RecycleScroller
},
// ...其他代码
}






