本周学习了js的,用老师教的敲了一个音乐播放器
准备工作
首先随便找首歌
然后用一个小工具扒它的歌词
前期准备完成
代码部分
现在就开始写 html 和 css 了
很简单 就不解释了 直接上代码
html
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 | <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8" /> <meta name="viewport" content="width=device-width, initial-scale=1.0" /> <meta http-equiv="X-UA-Compatible" content="ie=edge" /> <title>Music player</title> <link rel="stylesheet" href="index.css" /> </head> <body> <div class="container"> <audio id="MusicPlayer" src="media/袁娅维 - Starfall.flac" controls loop></audio> <div class="btn"> <button onclick="turn -= 0.1">-0.1s</button> <button onclick="turn += 0.1">+0.1s</button> </div> <div class="lrc"> <ul id="ullrc"> </ul> </div> </div> <script src="./index.js"></script> </body> </html> |
css
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 | *{ box-sizing: border-box; } body{ background: #000; } .container{ width: 100%; } .container #MusicPlayer{ width: 600px; display: block; margin: 0 auto; } .container .btn{ display: block; margin: 0 auto; } .container .lrc{ width: 700px; height: 450px; overflow: hidden; display: block; margin: 0 auto; } .container .lrc #ullrc{ width: 100%; padding: 0; list-style: none; transition: 0.3s all ease; margin: 0; } /*歌词普通样式*/ .container .lrc #ullrc li{ height: 35px; line-height: 35px; font-size: 1em; color: #aaa; font-weight: normal; transition: .3s all ease;/*一定要加上不然看着突兀*/ list-style-type: none; text-align: center; display: block; width: 100%; margin: 0 auto; } /*动态歌词样式*/ .container .lrc #ullrc li.active{ font-size: 1.2em; color: #fff; font-weight: bold; } |
js
完整js
先上完整js然后再讲一下
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 | var lrc = ` 歌词 歌词 歌词`; function $(id) { return document.getElementById(id); }//这样写以后getid方便 function getLrcArray() { var parts = lrc.split("\n"); for (let index = 0; index < parts.length; index++) { parts[index] = getLrcObj(parts[index]); } return parts; function getLrcObj(content) { var twoParts = content.split("]"); var time = twoParts[0].substr(1); var timeParts = time.split(":"); var seconds = +timeParts[1]; var min = +timeParts[0]; seconds = min * 60 + seconds; var words = twoParts[1]; return{ seconds: seconds, words: words, }; } } var lrcArray = getLrcArray(); function inputLrc() { for (let index = 0; index < lrcArray.length; index++) { var li = document.createElement("li"); li.innerText = lrcArray[index].words; $("ullrc").appendChild(li); } } inputLrc(); function setPosition() { var index = getLrcIndex(); if (index == -1) { return; } var lrc_li_height = 35, lrc_ul_height = 450; var top = index * lrc_li_height + lrc_li_height / 2 - lrc_ul_height / 2; if (top < 0) { top = 0; } $("ullrc").style.marginTop = -top + "px"; var activeLi = $("ullrc").querySelector(".active"); if(activeLi){ activeLi.classList.remove("active"); } $("ullrc").children[index].classList.add("active"); } var turn = 0; function getLrcIndex(){ var time = $("MusicPlayer").currentTime + turn; for (var index = 0; index < lrcArray.length; index++) { if (lrcArray[index].seconds > time) { return index - 1; } } } $("MusicPlayer").ontimeupdate = setPosition; |
那接下来就到了我们的重头戏了
首先我们得到了歌词
但是是这样的
第一步 歌词信息获取
我们要从这样的字符串中得到信息,就需要先把每段分割开来
接着再从每一段去获取它的时间和歌词俩个信息
那就这样写
1 2 3 4 | var lrc = ` 这里是一大堆歌词 `; var parts=lrc.split("\n"); |
这样就能把字符串根据回车分割开来,然后就是一步一步分割,直到达到我们要的格式
和上面一个逻辑就不解释了
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 | function getLrcArray() { //分割每一列 var parts = lrc.split("\n"); //遍历分割每一句 for (let index = 0; index < parts.length; index++) { parts[index] = getLrcObj(parts[index]); } return parts; function getLrcObj(content) { //把一句分割为俩部分 var twoParts = content.split("]"); var time = twoParts[0].substr(1);//将时间前的"["截掉 var timeParts = time.split(":");//用秒处理比较翻版我们这里这里转换成秒 var seconds = +timeParts[1]; var min = +timeParts[0]; seconds = min * 60 + seconds; //歌词获取 var words = twoParts[1]; return{//返回秒和歌词 seconds: seconds, words: words, }; } } var lrcArray = getLrcArray();//结果存储在这里 |
第二步 创建li
歌词文件都处理好了就没必要我们亲自去一个一个设置了,这里用js在页面上创建li元素
1 2 3 4 5 6 7 | function inputLrc() { for (let index = 0; index < lrcArray.length; index++) {//不用数,有多少句创建多少li标签 var li = document.createElement("li"); li.innerText = lrcArray[index].words;//歌词放入 $("ullrc").appendChild(li);//将这个li作为ul的子元素 } } |
就没了
第三步 歌词位置滚动
这里歌词位置的滚动就是根据修改
但是
我要让歌词居中显示,那么画一个模型出来是这样的
每次要让歌词的中间位置处于中线上,我们要算的其实就是溢出部分的高,将这个高写入
那问题来了,这个溢出部分的高怎么算呢.我们假设现在播放到了第i行歌词,也就是说要处在中线上的歌词就是第i行歌词,
根据下图可知
溢出部分的高度就是 * i 歌词行高 + 行高 / 2 - 460 / 2*
(为了数组遍历,i是从0开始的)
接着就是写一个active样式,把选中的歌词加上样式,把其他的active去掉即可
1 2 3 4 5 6 7 8 9 10 11 12 13 14 | function setPosition() { var index = getLrcIndex(); var lrc_li_height = 35, lrc_ul_height = 450;//定义行高和歌词box高度 var top = index * lrc_li_height + lrc_li_height / 2 - lrc_ul_height / 2;//计算 if (top < 0) { top = 0;//如果top为负说明歌词在开始几句,无需滚动,top归零 } $("ullrc").style.marginTop = -top + "px";//改变mt var activeLi = $("ullrc").querySelector(".active");//寻找ul下类名为active的元素并返回之 if(activeLi){ activeLi.classList.remove("active");//删 } $("ullrc").children[index].classList.add("active");//添 } |
歌词行数获取
接着只要得到歌词在哪一行就可以了
这个很简单
比较播放时间,出现播放时间小于数组存的时间的情况,直接返回index-1
1 2 3 4 5 6 7 8 | function getLrcIndex(){ var time = $("MusicPlayer").currentTime; for (var index = 0; index < lrcArray.length; index++) { if (lrcArray[index].seconds > time) { return index - 1; } } } |
因为最开始时返回值为 -1,所以还要在前面的调用中判断如果 index == -1 的话退出函数