vue如何实现歌词同步
Vue 实现歌词同步的方法
解析歌词文件
歌词文件通常为LRC格式,包含时间戳和歌词内容。需要将歌词解析为数组对象,每个对象包含时间(秒)和对应歌词。
function parseLRC(lrcText) {
const lines = lrcText.split('\n');
return lines.map(line => {
const timeMatch = line.match(/\[(\d{2}):(\d{2})\.(\d{2})\]/);
if (!timeMatch) return null;
const min = parseInt(timeMatch[1]);
const sec = parseInt(timeMatch[2]);
const hundredths = parseInt(timeMatch[3]);
const time = min * 60 + sec + hundredths / 100;
const text = line.replace(timeMatch[0], '').trim();
return { time, text };
}).filter(item => item);
}
存储歌词数据
在Vue组件中存储解析后的歌词数据和当前播放时间:
data() {
return {
lyrics: [],
currentTime: 0,
currentLineIndex: 0
}
}
监听音频播放时间
使用音频元素的timeupdate事件监听播放进度:
<audio ref="audio" @timeupdate="updateLyrics"></audio>
methods: {
updateLyrics() {
this.currentTime = this.$refs.audio.currentTime;
this.updateCurrentLine();
}
}
匹配当前歌词行
根据当前播放时间找到对应的歌词行:
methods: {
updateCurrentLine() {
for (let i = 0; i < this.lyrics.length; i++) {
if (this.currentTime < this.lyrics[i].time) {
this.currentLineIndex = Math.max(0, i - 1);
return;
}
}
this.currentLineIndex = this.lyrics.length - 1;
}
}
高亮显示当前歌词
在模板中渲染歌词并高亮当前行:
<div class="lyrics-container">
<div
v-for="(line, index) in lyrics"
:key="index"
:class="{ 'active': index === currentLineIndex }"
>
{{ line.text }}
</div>
</div>
添加样式效果
通过CSS实现歌词高亮和滚动效果:
.lyrics-container {
height: 300px;
overflow-y: auto;
text-align: center;
}
.lyrics-container div {
padding: 8px;
transition: all 0.3s;
}
.lyrics-container .active {
color: #42b983;
font-size: 1.2em;
font-weight: bold;
}
实现平滑滚动
自动滚动到当前歌词位置:
methods: {
scrollToCurrentLine() {
const container = this.$el.querySelector('.lyrics-container');
const activeLine = container.children[this.currentLineIndex];
if (activeLine) {
container.scrollTo({
top: activeLine.offsetTop - container.offsetHeight / 2,
behavior: 'smooth'
});
}
}
}
性能优化
对于长歌词列表,可以使用虚拟滚动技术:
computed: {
visibleLyrics() {
const start = Math.max(0, this.currentLineIndex - 10);
const end = Math.min(this.lyrics.length, this.currentLineIndex + 10);
return this.lyrics.slice(start, end);
}
}
实时歌词获取
如果需要从网络获取歌词,可以使用axios:
async fetchLyrics(songId) {
try {
const response = await axios.get(`/api/lyrics/${songId}`);
this.lyrics = parseLRC(response.data);
} catch (error) {
console.error('Failed to fetch lyrics', error);
}
}
动态歌词效果
实现逐字高亮效果需要更精确的时间戳解析:
function parseWordTiming(lrcText) {
// 解析包含逐字时间戳的歌词
// 返回包含每个单词开始时间和持续时间的数组
}






