vue实现歌词同步
实现歌词同步的基本思路
歌词同步的核心是将歌词文本与音频播放时间轴匹配,通过解析歌词文件(如LRC格式)获取时间戳和对应歌词,监听音频播放时间并动态高亮当前播放的歌词行。
解析LRC歌词文件
LRC格式通常为[mm:ss.xx]歌词文本,需通过正则表达式提取时间戳和歌词内容。以下为解析函数示例:
function parseLRC(lrcText) {
const lines = lrcText.split('\n');
const result = [];
const timeRegex = /\[(\d{2}):(\d{2})\.(\d{2})\]/;
lines.forEach(line => {
const matches = timeRegex.exec(line);
if (matches) {
const min = parseInt(matches[1]);
const sec = parseInt(matches[2]);
const centisec = parseInt(matches[3]);
const time = min * 60 + sec + centisec * 0.01;
const text = line.replace(timeRegex, '').trim();
if (text) result.push({ time, text });
}
});
return result.sort((a, b) => a.time - b.time);
}
监听音频播放进度
使用<audio>标签或第三方库(如howler.js)获取当前播放时间,与解析后的歌词时间戳对比:
data() {
return {
lyrics: [], // 解析后的歌词数组
currentLine: -1 // 当前高亮行索引
}
},
methods: {
updateLyric(currentTime) {
for (let i = 0; i < this.lyrics.length; i++) {
if (currentTime < this.lyrics[i].time) {
this.currentLine = i - 1;
break;
}
}
}
}
动态高亮当前歌词
通过:class绑定实现当前行高亮效果:
<div class="lyrics-container">
<div
v-for="(line, index) in lyrics"
:key="index"
:class="{ 'active': currentLine === index }"
>
{{ line.text }}
</div>
</div>
<style>
.active {
color: #42b983;
font-weight: bold;
}
</style>
平滑滚动效果
使用CSS过渡或JavaScript计算滚动位置,确保当前歌词始终在可视区域:
scrollToCurrent() {
const container = this.$el.querySelector('.lyrics-container');
const activeItem = container.querySelector('.active');
if (activeItem) {
container.scrollTo({
top: activeItem.offsetTop - container.offsetHeight / 2,
behavior: 'smooth'
});
}
}
处理空白歌词行
过滤无时间戳的歌词行(如歌曲信息),避免显示在界面中:
const filteredLyrics = parsedLyrics.filter(item => item.text && !item.text.startsWith('作词') && !item.text.startsWith('作曲'));
性能优化建议
对于长音频文件,采用二分查找替代线性搜索提升匹配效率:

findCurrentLine(time) {
let left = 0, right = this.lyrics.length - 1;
while (left <= right) {
const mid = Math.floor((left + right) / 2);
if (this.lyrics[mid].time < time) {
left = mid + 1;
} else {
right = mid - 1;
}
}
return right;
}






