前 言
上周更新了一篇音乐播放器的博客,因为时间原因,并不完整,有人评论我能不能实现同步显示歌词,今天就来跟大家分享一下,如何实现歌词的同步显示。
这次我们就不写过多的CSS样式了,单纯的实现歌词的同步显示,先看一下效果。
上周我们提到的audio标签,这次我们直接在audio标签中添加controls属性,这样我们的音乐播放器就自带工具栏了,也就是顶部的那一块,虽然不是太美观,但是麻雀虽小五脏俱全,基本功能都可以实现,当然,大家可以自己写样式~
<audio controls>
<source src="auto/赵雷 - 成都.mp3" type="audio/mpeg"/>
</audio>
<span class="wordsbtn" onclick="showWords()">词</span>
1解析歌词
首先我们需要下载一个lyric格式的歌词,这一步很重要,因为在同步歌词的时候需要通过时间来判断显示哪一句。我们以《成都》为例,把它放到预格式标签中~
<pre id="song1">
[ti:成都]
[ar:赵雷]
[al:无法长大]
[by:0]
[offset:0]
[00:01.34]成都
[00:02.09]
[00:03.96]作词:赵雷
[00:03.96]作曲:赵雷
[00:05.99]编曲:赵雷,喜子
[00:09.04]演唱:赵雷
[00:12.90]
[00:17.65]让我掉下眼泪的
[00:21.57]不止昨夜的酒
[00:25.82]让我依依不舍的
[00:29.62]不止你的温柔
[00:33.78]余路还要走多久
[00:37.64]你攥着我的手
[00:41.63]让我感到为难的
[00:45.47]是挣扎的*
[00:49.20]
[00:51.90]分别总是在九月
[00:55.38]回忆是思念的愁
[00:59.46]深秋嫩绿的垂柳
[01:03.32]亲吻着我额头
[01:07.31]在那座阴雨的小城里
[01:11.44]我从未忘记你
[01:15.56]成都 带不走的 只有你
[01:21.76]
[01:22.81]和我在成都的街头走一走
[01:31.25]直到所有的灯都熄灭了也不停留
[01:38.88]你会挽着我的衣袖
[01:42.67]我会把手揣进裤兜
[01:46.56]走到玉林路的尽头
[01:50.45]坐在小酒馆的门口
[01:55.65]
[02:30.35]分别总是在九月
[02:34.31]回忆是思念的愁
[02:38.17]深秋嫩绿的垂柳
[02:42.48]亲吻着我额头
[02:46.66]在那座阴雨的小城里
[02:50.34]我从未忘记你
[02:53.78]成都 带不走的 只有你
[03:00.95]
[03:02.38]和我在成都的街头走一走
[03:10.13]直到所有的灯都熄灭了也不停留
[03:18.32]你会挽着我的衣袖
[03:21.99]我会把手揣进裤兜
[03:25.99]走到玉林路的尽头
[03:29.79]坐在小酒馆的门口
[03:36.36]
[03:38.40]和我在成都的街头走一走
[03:46.45]直到所有的灯都熄灭了也不停留
[03:54.27]和我在成都的街头走一走
[04:02.30]直到所有的灯都熄灭了也不停留
[04:10.29]你会挽着我的衣袖
[04:13.57]我会把手揣进裤兜
[04:17.56]走到玉林路的尽头
[04:21.77]坐在(走过)小酒馆的门口
[04:27.72]
[04:36.02]和我在成都的街头走一走
[04:43.67]直到所有的灯都熄灭了也不停留
[04:51.93]
</pre>
这样所有的HTML代码部分就已经全部完成了,接下来就是我们的JS……
首先是解析歌词,这是首先要做的准备工作,同样也是最重要的一步,解析步骤大体如下:
①当页面加载完的时候,获取到歌词
②将歌词通过换行符将所有歌词放到数组中
③通过for循环,循环遍历每一行歌词,将歌词前不是时间的过滤掉
④由于audio标签的currentTime是以秒来记数,所以我们需要将歌词时间改为秒
⑤将每行歌词秒数与歌词内容封装成对象,放入数组中
//全局的歌词数据
var wordsArray=[];
window.onload=function(){
//获取歌词并且截取
var content=document.getElementById("song1").innerHTML;
//通过换行符来分割出所有的文本\n
var arrays=content.split("\n");
//过滤掉前几个不带时间的数据
for(var i=0;i<arrays.length;i++){
var temp=arrays[i];
//根据分号分割过滤数据
var tempNum=temp.split(":")[0].replace("[","");
//是合法歌词的时候
if(!isNaN(tempNum)){
//重新根据]来分割 ,分离数据
var timeArray=temp.split("]")[0].replace("[","").split(":");//33:44
//计算分钟数
var min=parseInt(timeArray[0]);
//计算总秒数
var second=parseFloat(timeArray[1])+min*60;
//获取对应的歌词内容
var content=temp.split("]")[1];
//封装成歌词对象放入数组
var obj={
time:second,
content:content
};
wordsArray.push(obj);
}
}
}
这样,我们的准备工作就完成了~
2歌词滚动
点击span播放按钮的时候,触发一个showWords函数,将显示歌词的div显示到界面中。将存在数组中的对象的时间通过与当前播放时间currentTime进行对比,当当前播放时间大于数组中对象的时间,那么久显示这一句的歌词。
具体实现:
①获取到显示歌词的div将div显示
②设置一个定时器,每秒比较一次(将当前播放时间与解析出的数组中的对象时间进行比较,如果播放的秒数大于数组中的秒数,播放前一句歌词)
function showWords(){
var words=document.getElementsByClassName("words")[0];
//控制歌div显示或者隐藏
if(words.style.display=="none"){
words.style.display="block";
}else{
words.style.display="none";
}
//开始获取歌词并且展示到歌词框
var play=document.getElementsByTagName("audio")[0];
setInterval(function(){
var str= getWordsByTime(play.currentTime);
document.getElementsByClassName("words")[0].innerHTML=str;
},1000);
}
//根据时间获取当前应该显示哪一句话
function getWordsByTime(second){
for(var i in wordsArray){
var obj=wordsArray[i];
if(second>obj.time){ //播放时候的秒数大于数组中的秒数的时候,播放的应该是前一句歌词
continue;
}else{
return wordsArray[i-1].content;
}
}
}
这样,同步显示歌词的功能就完成了啦~