实现歌词同步滚动效果,首先要用
audio
标签引入音频
<div id="h_center1"> <span>当前播放:</span> <span>大鱼海棠</span> <audio id="now_music" src="双笙 - 大鱼.mp3"></audio> <img src="picture/former.jpg"/> <img src="picture/stop.jpg" class="clickToStop" width="21" height="58"/> <img src="picture/next.jpg"/> </div>
并且也要将歌词文件写入
textarea
文本域内并隐藏,然后在获取歌词时放入指定位置
<textarea id="lrc_content" name="textfield" cols="70" rows="10" style="display:none;"> [ti:大鱼] [ar:王若伊] [al:大鱼] [ly:尹约] [mu:钱雷] [ma:] [pu:] [by:ttpod] [total:278752] [offset:0] [00:00.410]大鱼 - 王若伊 [00:01.410]作词:尹约 [00:02.310]作曲:钱雷 [00:03.161] [00:44.447]海浪无声将夜幕深深淹没 [00:51.200]漫过天空尽头的角落 [00:57.995]大鱼在梦境的缝隙里游过 [01:04.848]凝望你沉睡的轮廓 [01:10.898]看海天一色 听风起雨落 [01:17.705]执子手吹散苍茫茫烟波 [01:24.506]大鱼的翅膀 已经太辽阔 [01:32.112]我松开时间的绳索 [01:38.017]怕你飞远去 [01:41.620]怕你离我而去 [01:45.173]更怕你永远停留在这里 [01:51.876]每一滴泪水 [01:55.428]都向你流淌去 [01:59.623]倒流进天空的海底 [02:05.201] [02:20.568]海浪无声将夜幕深深淹没 [02:27.118]漫过天空尽头的角落 [02:34.029]大鱼在梦境的缝隙里游过 [02:40.733]凝望你沉睡的轮廓 [02:47.051]看海天一色 听风起雨落 [02:53.654]执子手吹散苍茫茫烟波 [03:00.637]大鱼的翅膀 已经太辽阔 [03:08.087]我松开时间的绳索 [03:14.187]看你飞远去 看你离我而去 [03:21.039]原来你生来就属于天际 [03:27.889]每一滴泪水 都向你流淌去 [03:35.540]倒流回最初的相遇 </textarea> <ul id="text" style="overflow: hidden;"> </ul>
首先要把获取到的歌词解析为对象数组,并且放入指定位置,并且溢出隐藏
(t.split(“:”)[0] * 60 + parseFloat(t.split(“:”)[1])).toFixed(3)
这里是要把原来的mm:ss的时间格式改为秒
var medisArray = new Array(); // 定义一个新的数组 function createLrc () { var medis = document.getElementById('lrc_content').innerText; var medises = medis.split("\n"); // 用换行符拆分获取到的歌词 $.each(medises, function (i, item) { // 遍历medises,并且将时间和文字拆分开,并push进自己定义的数组,形成一个对象数组 var t = item.substring(item.indexOf("[") + 1, item.indexOf("]")); medisArray.push({ t: (t.split(":")[0] * 60 + parseFloat(t.split(":")[1])).toFixed(3), c: item.substring(item.indexOf("]") + 1, item.length) }); }); var ul = $("#text"); // 遍历medisArray,并且生成li标签,将数组内的文字放入li标签 $.each(medisArray, function (i, item) { var li = $("<li style='list-style: none;'>"); li.html(item.c); ul.append(li); }); } createLrc();
实现文字高亮滚动
var fraction = 0.5; var topNum = 0; function lineHeight(lineno){ var ul = $("#text"); var $ul = document.getElementById('text'); // 令正在唱的那一行高亮显示 if (lineno > 0) { $(ul.find("li").get(topNum + lineno - 1)).removeClass("lineheight"); } var nowline = ul.find("li").get(topNum + lineno); $(nowline).addClass("lineheight"); // 实现文字滚动 var _scrollTop; $ul.scrollTop = 0; if ($ul.clientHeight * fraction > nowline.offsetTop) { _scrollTop = 0; } else if (nowline.offsetTop > ($ul.scrollHeight - $ul.clientHeight * (1 - fraction))) { _scrollTop = $ul.scrollHeight - $ul.clientHeight; } else { _scrollTop = nowline.offsetTop - $ul.clientHeight * fraction; } //以下声明歌词高亮行固定的基准线位置成为 “A” if ((nowline.offsetTop - $ul.scrollTop) >= $ul.clientHeight * fraction) { //如果高亮显示的歌词在A下面,那就将滚动条向下滚动,滚动距离为 当前高亮行距离顶部的距离-滚动条已经卷起的高度-A到可视窗口的距离 $ul.scrollTop += Math.ceil(nowline.offsetTop - $ul.scrollTop - $ul.clientHeight * fraction); } else if ((nowline.offsetTop - $ul.scrollTop) < $ul.clientHeight * fraction && _scrollTop != 0) { //如果高亮显示的歌词在A上面,那就将滚动条向上滚动,滚动距离为 A到可视窗口的距离-当前高亮行距离顶部的距离-滚动条已经卷起的高度 $ul.scrollTop -= Math.ceil($ul.clientHeight * fraction - (nowline.offsetTop - $ul.scrollTop)); } else if (_scrollTop == 0) { $ul.scrollTop = 0; } else { $ul.scrollTop += $(ul.find('li').get(0)).height(); } }
监听
audio
的timeupdate
事件,实现文字与音频的同步
如果medisArray[lineNo].t <=T && T<= medisArray[lineNo + 1].t
,那么行号为lineNo的这行歌词就需要高亮
var lineNo = 10; audio.ontimeupdate = function () { if (lineNo == medisArray.length - 1 && audio.currentTime.toFixed(3) >= parseFloat(medisArray[lineNo].t)) { lineHeight(lineNo); } if (parseFloat(medisArray[lineNo].t) <= audio.currentTime.toFixed(3) && audio.currentTime.toFixed(3) <= parseFloat(medisArray[lineNo + 1].t)) { lineHeight(lineNo); lineNo++; } };
文章来源: JS实现歌词同步滚动效果