实现歌词同步滚动效果,首先要用
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>
JS实现
首先要把获取到的歌词解析为对象数组,并且放入指定位置,并且溢出隐藏
(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++;
}
};