1200字范文,内容丰富有趣,写作的好帮手!
1200字范文 > js解析lrc 实现lrc歌词同步滚动效果

js解析lrc 实现lrc歌词同步滚动效果

时间:2018-11-12 20:15:54

相关推荐

js解析lrc 实现lrc歌词同步滚动效果

这两天想着做一个h5的网页播放器,实现歌词同步滚动

但是上网找了很多资料,竟发现没有比较完善的代码供参考,但是无意间看到了百度的千千音乐有这样的效果,就想着一定能通过js实现

经过两三天的努力,终于做出了这样的效果

实现功能

歌词同步滚动同步歌词高亮效果

代码实现

首先,在body中加audio 和 放歌词的ul标签

<div><ul id="lrclist" style="transform: translateY(250px);"><!-- 保证歌词在正中间 --></ul></div><audio id="audio" src="audio/1.mp3" controls="controls" autoplay="true"></audio>

然后就是读取lrc文件,在进行解析,解析出歌词及对应的时间

一般的思路是这样的:通过Ajax或其他方式读取lrc文件

但我的专业是后端开发,js,啥的,都是自学的,于是遇到了不少坑,,在我千方百计想获取lrc文件时,总是报错,,只能通过http,data 协议获取文件,加上我用的是notepad开发的,调试了亿遍都失败

最后只好放弃了,我把lrc数据直接定义在js中,最后实现了同样的效果,

var lrcJSON = {"[00:16.810]":"誰にも言えない孤独を抱えたまま1人で泣いてた","[00:28.040]":"誰にも上手に笑えない僕ら 2人出会って笑った","[00:39.710]":"","[00:40.410]":"真夜中過ぎに 想像の奥に","[00:46.150]":"どうしようもない気持ちをただ押しやって","[00:50.780]":"","[00:51.480]":"サヨナラ 僕らはきっと生まれ変われるから","[00:57.030]":"悲しみに手を振るんでしょう","[01:01.190]":"そしていつか 空っぽのままの心に灯りをともすように","[01:08.630]":"とぎれとぎれの 言葉を探して繋ぎ止めた","[01:14.390]":"それでもたった二人の世界は続いて行くんだ","[01:20.190]":"空に祈るように どうか永遠に","[01:29.380]":"","[01:43.670]":"白・黒・壱・零 僕らは選ぶ事を迫られてばかり","[01:54.940]":"そうして残った大事な物を壊れるほど抱きしめていた","[02:06.670]":"","[02:07.670]":"明け方過ぎの光の先に","[02:13.530]":"ほんの少しだけ未来が見えた気がして","[02:18.110]":"","[02:18.810]":"バカげた夢だってきっと願い続けるから","[02:24.330]":"奇跡に近づくんでしょう","[02:28.590]":"それは君の弱さの隣に見つけた強さの欠片だって","[02:36.160]":"とぎれとぎれの 言葉を探して繋ぎ止めた","[02:41.700]":"瞼の奥に滲んだ世界を守ってゆくんだ","[02:47.470]":"空に祈るように 君と誓う明日","[02:58.720]":"","[03:08.900]":"不自由な思いが重なり合ったら","[03:14.390]":"そうさ誰より自由になれた","[03:20.390]":"足りないものを埋め合うように","[03:25.700]":"疑いもせず 支えあいながら","[03:31.610]":"","[03:34.060]":"サヨナラ 僕らはきっと生まれ変われるから","[03:39.490]":"悲しみに手を振るんでしょう","[03:44.450]":"そしていつか 空っぽのままの心に灯りをともすように","[03:51.620]":"とぎれとぎれの 言葉を探して繋ぎ止めた","[03:57.190]":"それでもたった二人の世界は続いて行くんだ","[04:03.000]":"空に祈るように どうか永遠に…"};

(有需要的可以仿照网上的Ajax获取lrc文件,再进行解析)

(不过lrc歌词文件可没有那么简单,开头可能还有歌名,歌手等信息,后边可能还有歌词对应的翻译。这里我是简化了数据。)

然后获取lrc数据,在ul中填充歌词,同时获取歌词对应的时间数据

var lrcTime = [];//歌词对应的时间数组var ul = $("#lrclist")[0];//获取ulvar i = 0;$.each(lrcJSON, function(key, value) {//遍历lrclrcTime[i++] = parseFloat(key.substr(1,3)) * 60 + parseFloat(key.substring(4,10));//00:00.000转化为00.000格式ul.innerHTML += "<li><p>"+lrcJSON[key]+"</p></li>";//ul里填充歌词});

接下来是播放时的自动滚动,用到了audio的timeupdate事件

audio.ontimeupdate = function() {//audio时间改变事件currentTime = audio.currentTime;for (j=currentLine, len=lrcTime.length; j<len; j++){if (currentTime<lrcTime[j+1] && currentTime>lrcTime[j]){currentLine = j;ppxx = 250-(currentLine*32);ul.style.transform = "translateY("+ppxx+"px)";$li.get(currentLine-1).className="";console.log("on"+currentLine);$li.get(currentLine).className="on";break;}}};

最后是调整播放位置时触发的audio的seeked事件

audio.onseeked = function() {//audio进度更改后事件currentTime = audio.currentTime;console.log(" off"+currentLine);$li.get(currentLine).className="";for (k=0, len=lrcTime.length; k<len; k++){if (currentTime<lrcTime[k+1] && currentTime<lrcTime[k]){currentLine = k;break;}}};

实现效果

最后附上完整代码

<!DOCTYPE html><html><head><meta charset="utf-8"><meta name="viewport" content="width=device-width, initial-scale=1, minimum-scale=1, maximum-scale=1, user-scalable=no"><title>LRC</title><script src="js/jquery.js"></script><style>div{width:340px;height:500px;margin:0 auto;overflow:hidden;}ul{transition-duration: 600ms;}ul, li{list-style:none;padding: 0;margin: 0;}li.on{color: red;}p{overflow: hidden;text-overflow: ellipsis;height: 16px;line-height: 16px;-webkit-line-clamp: 1;-webkit-box-orient: vertical;display: -webkit-box;text-align: center;margin-top: 0;margin-bottom: 16px;}audio{margin-top: 10px;}</style></head><body><div><ul id="lrclist" style="transform: translateY(250px);"><!-- 保证歌词在正中间 --></ul></div><audio id="audio" src="audio/1.mp3" controls="controls" autoplay="true"></audio><script>var lrcJSON = {"[00:16.810]":"誰にも言えない孤独を抱えたまま1人で泣いてた","[00:28.040]":"誰にも上手に笑えない僕ら 2人出会って笑った","[00:39.710]":"","[00:40.410]":"真夜中過ぎに 想像の奥に","[00:46.150]":"どうしようもない気持ちをただ押しやって","[00:50.780]":"","[00:51.480]":"サヨナラ 僕らはきっと生まれ変われるから","[00:57.030]":"悲しみに手を振るんでしょう","[01:01.190]":"そしていつか 空っぽのままの心に灯りをともすように","[01:08.630]":"とぎれとぎれの 言葉を探して繋ぎ止めた","[01:14.390]":"それでもたった二人の世界は続いて行くんだ","[01:20.190]":"空に祈るように どうか永遠に","[01:29.380]":"","[01:43.670]":"白・黒・壱・零 僕らは選ぶ事を迫られてばかり","[01:54.940]":"そうして残った大事な物を壊れるほど抱きしめていた","[02:06.670]":"","[02:07.670]":"明け方過ぎの光の先に","[02:13.530]":"ほんの少しだけ未来が見えた気がして","[02:18.110]":"","[02:18.810]":"バカげた夢だってきっと願い続けるから","[02:24.330]":"奇跡に近づくんでしょう","[02:28.590]":"それは君の弱さの隣に見つけた強さの欠片だって","[02:36.160]":"とぎれとぎれの 言葉を探して繋ぎ止めた","[02:41.700]":"瞼の奥に滲んだ世界を守ってゆくんだ","[02:47.470]":"空に祈るように 君と誓う明日","[02:58.720]":"","[03:08.900]":"不自由な思いが重なり合ったら","[03:14.390]":"そうさ誰より自由になれた","[03:20.390]":"足りないものを埋め合うように","[03:25.700]":"疑いもせず 支えあいながら","[03:31.610]":"","[03:34.060]":"サヨナラ 僕らはきっと生まれ変われるから","[03:39.490]":"悲しみに手を振るんでしょう","[03:44.450]":"そしていつか 空っぽのままの心に灯りをともすように","[03:51.620]":"とぎれとぎれの 言葉を探して繋ぎ止めた","[03:57.190]":"それでもたった二人の世界は続いて行くんだ","[04:03.000]":"空に祈るように どうか永遠に…"};var lrcTime = [];//歌词对应的时间数组var ul = $("#lrclist")[0];//获取ulvar i = 0;$.each(lrcJSON, function(key, value) {//遍历lrclrcTime[i++] = parseFloat(key.substr(1,3)) * 60 + parseFloat(key.substring(4,10));//00:00.000转化为00.000格式ul.innerHTML += "<li><p>"+lrcJSON[key]+"</p></li>";//ul里填充歌词});lrcTime[lrcTime.length] = lrcTime[lrcTime.length-1] + 3;//如不另加一个结束时间,到最后歌词滚动不到最后一句var $li = $("#lrclist>li");//获取所有livar currentLine = 0;//当前播放到哪一句了var currentTime;//当前播放的时间var audio = document.getElementById("audio");var ppxx;//保存ul的translateY值audio.ontimeupdate = function() {//audio时间改变事件currentTime = audio.currentTime;for (j=currentLine, len=lrcTime.length; j<len; j++){if (currentTime<lrcTime[j+1] && currentTime>lrcTime[j]){currentLine = j;ppxx = 250-(currentLine*32);ul.style.transform = "translateY("+ppxx+"px)";$li.get(currentLine-1).className="";console.log("on"+currentLine);$li.get(currentLine).className="on";break;}}};audio.onseeked = function() {//audio进度更改后事件currentTime = audio.currentTime;console.log(" off"+currentLine);$li.get(currentLine).className="";for (k=0, len=lrcTime.length; k<len; k++){if (currentTime<lrcTime[k+1] && currentTime<lrcTime[k]){currentLine = k;break;}}};</script></body></html>

可能会有点不足之处,还望大佬们指正

本内容不代表本网观点和政治立场,如有侵犯你的权益请联系我们处理。
网友评论
网友评论仅供其表达个人看法,并不表明网站立场。