JS实现播放音乐时歌词同步展示
效果如下:
实现过程:
监听音频播放时间,使用歌词的出现时间与其比较,展示对应时间歌词内容,代码如下
<audio id="audio-player" src="每个眼神都只身荒野.m4a" controls></audio> <div class="lyrics-container"> <div id="lyrics"></div> </div> <script> document.addEventListener('DOMContentLoaded', function() { var audio = document.getElementById('audio-player'); var lyricsContainer = document.getElementById('lyrics'); // 歌词内容与时间 var lyrics = [ { time: 3, text: "在每个眼神都只身荒野那瞬间" }, { time: 10, text: "你和我面对面如此地安慰" }, { time: 18, text: "如果我能发现" }, { time: 22, text: "动情的灵魂终将在前夜告别" }, { time: 26, text: "我也不愿停下仅有时间" }, { time: 29, text: "让我忘了我是谁" }, // 歌词时间和文本继续添加 ]; // 更新歌词 function updateLyrics(currentTime) { for (var i = 0; i < lyrics.length; i++) { if (currentTime >= lyrics[i].time && (!lyrics[i + 1] || currentTime < lyrics[i + 1].time)) { lyricsContainer.innerText = lyrics[i].text; break; } } } // 监听频播放时间更新事件 audio.addEventListener('timeupdate', function() { var currentTime = audio.currentTime; updateLyrics(currentTime); }); }); </script>
这样将歌词在js里面固定了,可以将歌词抽出成一个Irc文件,将该文件放在服务器上面,使其能用http访问到。
同时在js中获取Irc文件的内容,并沿用上面的实现,整个html文件如下
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Music歌词同步展示</title> <style> .lyrics-container { text-align: left; height: 30px; } #lyrics { margin-top: 5px; font-size: 20px; line-height: 1.5; } </style> </head> <body> <audio id="audio-player" src="http://服务器IP/每个眼神都只身荒野.m4a" controls></audio> <div class="lyrics-container"> <div id="lyrics" src="http://服务器IP/每个眼神都只身荒野.lrc"></div> </div> <script> let audio = document.getElementById('audio-player'); let lyricsContainer = document.getElementById('lyrics'); let lyricsPath = lyricsContainer.getAttribute('src'); console.log(lyricsPath); // 创建一个空数组来存储歌词数据 let ircArray = []; // 匹配时间和文本的正则表达式模式 const pattern = /\[(\d+:\d+.\d+)\](.+)/g; document.addEventListener('DOMContentLoaded', function() { // 更新展示的歌词 function updateLyrics(currentTime) { for (var i = 0; i < ircArray.length; i++) { if (currentTime >= ircArray[i].time && (!ircArray[i + 1] || currentTime < ircArray[i + 1].time)) { lyricsContainer.innerText = ircArray[i].text; break; } } } // 监听频播放时间更新事件 audio.addEventListener('timeupdate', function() { var currentTime = audio.currentTime; updateLyrics(currentTime); }); }); const xhr = new XMLHttpRequest(); xhr.open('GET', lyricsPath); xhr.onreadystatechange = function() { if (xhr.readyState === XMLHttpRequest.DONE) { if (xhr.status === 200) { console.log(xhr.responseText); // 在数据中匹配正则表达式模式并提取时间和文本 let match; while ((match = pattern.exec(xhr.responseText)) !== null) { let time = match[1]; // 获取时间 let text = match[2]; // 获取文本 // 将时间转换为秒数,格式为 mm:ss.xxxx let [minutes, seconds] = time.split(':'); let [secondsPart, milliseconds] = seconds.split('.'); let timeInSeconds = parseInt(minutes) * 60 + parseInt(secondsPart) + parseFloat(`0.${milliseconds}`); // 创建包含 time 和 text 属性的对象 let ircObject = { time: timeInSeconds, text: text }; // 将对象添加到数组中 ircArray.push(ircObject); } console.log(ircArray); // 在请求成功且数据处理完毕后打印数组内容 } else { // 处理错误 console.error('请求出错:', xhr.status); } } }; xhr.send(); </script> </body> </html>
拓展:展示前3行、当前行和后4行歌词
效果如下
audio.addEventListener('timeupdate', function() { var currentTime = audio.currentTime; var currentLineIndex = 0; // 清空歌词容器 lyricsContainer.innerHTML = ''; // 遍历歌词数据,查找当前播放时间对应的歌词 for (var i = 0; i < ircArray.length; i++) { if (ircArray[i].time <= currentTime) { currentLineIndex = i; } } // 显示当前行及前3行、后4行的歌词 var startIndex = Math.max(0, currentLineIndex - 3); var endIndex = Math.min(ircArray.length - 1, currentLineIndex + 4); for (var j = startIndex; j <= endIndex; j++) { var line = ircArray[j]; var lineElement = document.createElement('p'); if (j === currentLineIndex) { lineElement.classList.add('currentLine'); } lineElement.innerText = line.text; lyricsContainer.appendChild(lineElement); } // 滚动歌词容器 var currentLineElement = lyricsContainer.querySelector('.currentLine'); if (currentLineElement) { lyricsContainer.scrollTop = currentLineElement.offsetTop - lyricsContainer.offsetHeight / 2; } });