本人目前准备利用闲暇时间打造一个完整的音乐播放器项目,主要用于学习及分享!原创不易,转载请注明出处。
这是一个什么样的音乐播放器呢?整体的架构跟酷狗差不多吧,我的方式呢,是一个个组件一个个模块先做好,最后组合成完整的项目,最后项目会放在本人的github上,等项目完毕后会发布链接。
模块①、歌词同步:(为了方便测试,先用了h5集成好的audio标签,我们只做歌词功能),初步效果是这样:(另外直接在酷狗下载歌词文件就可以用了)
这个其实不难,不过呢,咱用点最笨的办法(关于解析字符串,不用正则匹配),酷狗都用过吧,里面的歌词文件是.krc文件,这种文件是加密过的,所以呢,从酷狗下载下来的歌词文件需要先转化成lrc文件,推荐下面的软件:
krc文件点开是这样的:
转化成lrc文件后是这样的:
扫描二维码关注公众号,回复:
973618 查看本文章
注意这时候lrc文件的字符编码不是utf-8,各位需要自行另存为utf-8文件,好了,歌词文件准备好了,可以开始我们的歌词模块了。
css及js文件我全部放在html里,完善后会逐步封装,css会采用less代替。
1 <!DOCTYPE html> 2 <html lang="en"> 3 <head> 4 <meta charset="UTF-8"> 5 <title>基于js的更高级常用函数封装</title> 6 <script src="../js/jquery-3.3.1.min.js" type="text/javascript"></script> 7 <script src="../js/mine/dc-handle-function.js" type="text/javascript"></script> 8 <style> 9 .preload{ 10 width:200px; 11 height:100px; 12 position:absolute; 13 top:35%; 14 left:40%; 15 } 16 .preload img{ 17 width:100%; 18 height:100%; 19 } 20 .lyric{ 21 width:400px; 22 height:500px; 23 margin:0 auto; 24 display:none; 25 overflow-y:auto; 26 overflow-x:hidden; 27 font:18px "华文楷体"; 28 color:black; 29 text-align: center; 30 box-shadow:-2px 2px 15px #fff; 31 background:rgba(0,255,255,0.3); 32 } 33 .music{ 34 width:400px; 35 margin:0 auto; 36 } 37 .music audio{ 38 width:100%; 39 } 40 body{ 41 overflow:scroll; 42 background:url("../resource/bg.jpg") fixed no-repeat;background-size:cover; 43 } 44 </style> 45 <script> 46 $(function(){ 47 dorseyHf.dc_ajax_g('../resource/av/ChiQingZhong1.lrc?t='+new Date().getTime(), 48 function(str){ 49 //这个函数以后也是会封装的。 50 var str1=str.split("["); 51 var str2=[]; 52 var lyric=$(".lyric"); 53 for(var i=1;i<str1.length;i++){ 54 str2[i-1]=str1[i].split("]"); 55 } 56 for(let i=0;i<str2.length;i++){ 57 if(lyric.children('p').length==0){ 58 lyric.append('<p></p>'); 59 } 60 lyric.children('p').eq(i).html(str2[i][1]); 61 lyric.append('<p></p>'); 62 } 63 lyric.css("display","block"); 64 //str3: "00:00.09",即获取到歌词的前半部分[时间]; 65 var str3=[],str4=[],str5=[]; 66 for(var i=2;i<str2.length;i++){ 67 str3[i-2]=str2[i][0]; 68 } 69 //str4: str4[i][0]="00";str4[i][1]="00.09" 70 //str5:计算str4转化后min:sec的值,单位(s),用于后续与当前时间比较。 71 for(var i=0;i<str3.length;i++){ 72 str4[i]=str3[i].split(":"); 73 str5[i]=(parseFloat(str4[i][0])*60)+parseFloat(str4[i][1]); 74 console.log("p"+i+":"+lyric.children('p').eq(i+2).offset().top); 75 } 76 $('audio').on("timeupdate",function(){ 77 var scale=this.currentTime; 78 var k=[]; 79 for(var i=0;i<str5.length;i++){ 80 if(scale>=str5[i]){ 81 lyric.children('p').eq(i+2).css("color","red").siblings().css("color",""); 82 lyric.children('p').eq(i+2).css("transform","scale(1.4)").siblings().css("transform",""); 83 k[i]=i; 84 // lyric.scrollTop(lyric.children('p').eq(i).offset().top); 85 } 86 } 87 var music=k.length; 88 console.log(music+": "+lyric.children('p').eq(music).offset().top); 89 }); 90 },$('img')); 91 }) 92 </script> 93 </head> 94 <body> 95 <div class="music"> 96 <audio src="../resource/av/ChiQingZhong.mp3" controls="controls"></audio> 97 </div> 98 <div class="preload"> 99 <img src="../resource/preload.gif" alt=""> 100 </div> 101 <div class="lyric"> 102 </div> 103 </body> 104 </html>
这里引用了一些封装函数,需引入这个文件,jq的压缩版自行百度:
1 ;(function(win){ //前面这分号别去掉哦,防止多个js文件合并压缩时因上一个js文件末尾少";"而带来的问题。 2 3 "use strict"; //严格模式,一般写自己类库的时候最好加上,减少一些代码不规范引起的错误。 4 5 /*模块说明:dorseyHf作为一切处理函数的入口*/ 6 let dorseyHf=function(){ 7 return new dorseyHf.fn.init(); 8 }; 9 dorseyHf.fn=dorseyHf.prototype={ 10 constructor:dorseyHf, //接口名:是dorsey-handle-function的缩写。意为函数处理 11 init:function(){ 12 return this; 13 }, 14 math:{//数学相关处理函数,注意需要通过接口dorseyHf来调用,如dorseyHf.math.random(100,200); 15 random:function(min,max){//生成一个指定范围大小的随机数,默认值小数点后15位 16 return Math.random()*(max-min)+min; 17 }, 18 randomAccuracy:function(min,max,dec){ //生成一个可以任意指定精度的随机数 19 return Math.round((Math.random()*(max-min)+min)*Math.pow(10,dec))/Math.pow(10,dec); 20 } 21 }, 22 dc_ajax_g:function(url,fnSucceed,preObj,fnFail){//ajax获取操作 23 /** 24 * url:可以是后台接口,json数据,也可以是json文件位置 25 * fnSucceed:ajax获取成功后的操作 26 * preObj:预加载,ajax由于要与后台服务器做交互,这需要时间,特别是前后交互数据较大时,用于提醒用户 27 * 现在在做加载,请稍后...一般是一个gif,或者干脆一个请稍后都行,注意的是基于JQuery的$(select)对象。 28 * fnFail:ajax获取失败后返回的操作,一般类似于404这样的东西。 29 * */ 30 preObj.css("display","block"); 31 setTimeout(function(){ 32 var oAjax = new XMLHttpRequest(); 33 oAjax.open('GET',url,true); 34 oAjax.send(); 35 oAjax.onreadystatechange=function(){ 36 if(oAjax.readyState==4){ 37 if(oAjax.status==200){ 38 fnSucceed(oAjax.responseText);//获取文本或者json数据 39 preObj.css("display","none"); 40 } 41 else{ 42 if(fnFail){ 43 fnFail(oAjax.status); 44 } 45 } 46 } 47 }; 48 },1500);//这个延迟最好改为0,或者干脆把setTimeout去掉,这样加的原因是方便那些ajax获取过快的 49 // 用户可以查看到这个预加载的效果。 50 } 51 }; 52 dorseyHf=dorseyHf.fn.init.fn=dorseyHf.fn; 53 win.dorseyHf=dorseyHf; 54 })(window);
后续每个模块写好了会逐步更新,等项目最终完毕了会挂载到github,各位到时可自行下载。