美文网首页web基础学习之路
第十三周之QQ音乐移动端项目实战代码

第十三周之QQ音乐移动端项目实战代码

作者: 果木山 | 来源:发表于2018-11-18 22:11 被阅读0次

    QQ音乐移动端项目实战代码:

    • html代码:
       <!DOCTYPE html>
       <html lang="en">
       <head>
           <meta charset="UTF-8">
           <meta name="viewport" content="width=device-width, initial-scale=1.0">
           <title>QQ音乐实战</title>
           <link rel="stylesheet" type="text/less" href="css/index.less">
           <script src="js/less.min.js"></script>
       </head>
       <body>
       <section class="musicBox">
           <div class="musicbg"></div>
           <div class="musicshadow"></div>
           <header class="clearfix">
               <div class="h-left">
                   <img src="img/piao.jpg" alt="">
                   <p>
                       <span>天空</span><br/>
                       <span>朴信惠</span>
                   </p>
               </div>
               <div class="h-right">
                   <div class="hr-play"></div>
                   <div class="hr-pause"></div>
               </div>
           </header>
           <section class="main">
               <div class="lyc">
                   <!--<p>天空 - 朴信惠</p>
                   <p>词:周耀辉</p>
                   <p>曲:李荣浩</p>
                   <p>穿华丽的服装 为原始的渴望而站着</p>-->
               </div>
           </section>
           <footer>
               <div class="storage">
                   <p></p>
               </div>
               <audio src="music/cc.mp3"></audio>
               <div class="progressWrap clearfix">
                   <div class="current">00:00</div>
                   <div class="progress">
                       <div class="time-line"></div>
                   </div>
                   <div class="duration">00:00</div>
               </div>
               <div class="download"><a href="#">下载这首歌</a></div>
           </footer>
       </section>
       <script src="js/jquery.js"></script>
       <script src="js/zepto.js"></script>
       <script src="js/index.js"></script>
       </body>
       </html>
      
    • less代码:
       @import "reset.less";
       @import (reference)"public.less";
       html,body{
         width: 100%;
         height: 100%;
       }
       .musicBox{
         width: 100%;
         height: 100%;
         position: relative;
         .musicbg{
           width: 100%;
           height: 100%;
           position: absolute;
           left: 0;
           top: 0;
           z-index: -2;
           background: url("../img/piao.jpg") no-repeat center;
           background-size: cover;
           -webkit-filter: blur(5px);
           filter: blur(5px);
         }
         .musicshadow{
           width: 100%;
           height: 100%;
           position: absolute;
           left: 0;
           right: 0;
           z-index: -1;
           background-color: rgba(1,1,1,.3);
         }
       }
       //header
       header{
         padding: .3rem;
         color: @color-white;
         background-color: rgba(0,0,0,.3);
         .h-left{
           float: left;
           >img{
             float: left;
             width: 1.2rem;
             height: 1.2rem;
             margin-right: .4rem;
           }
           >p{
             float: left;
             font-size: .35rem;
             >span{
               line-height: .63rem;
             }
           }
         }
         .h-right{
           float: right;
           width: .8rem;
           height: .8rem;
           border-radius: 50%;
           border: 1px solid @color-white;
           box-sizing: border-box;
           margin-top: .2rem;
           margin-right: .1rem;
           position: relative;
           cursor: pointer;
           outline: none;
           .hr-play,.hr-pause{
             position: absolute;
             width: .4rem;
             height: .4rem;
             left: 50%;
             top:50%;
             margin-top: -.2rem;
             margin-left: -.2rem;
           }
           .hr-play{
             .spriteFn(@x:-.4rem,@y:-1.3rem);
           }
           .hr-pause{
             .spriteFn(@x:-.4rem,@y:-.36rem);
             display: none;
           }
         }
       }
       //main
       .main{
         margin: .4rem .2rem;
         overflow: hidden;
         position: relative;
         .lyc{
           position: absolute;
           transition: all 1s;
           >p{
             text-align: center;
             font-size: .32rem;
             line-height: .84rem;
             color: darken(@color-white,20%);
           }
           >p.active{
             color:@color-green;
           }
         }
       }
       //footer
       footer{
         margin: 0 .3rem;
         height: 3rem;
         color: darken(@color-white,10%);
         .storage{
           height: .8rem;
           >p{
             width: .6rem;
             height: .6rem;
             .spriteFn(@x:-2.185rem,@y:-.285rem);
             border-radius: 50%;
             border: 1px solid red;
             box-sizing: border-box;
             float: right;
             margin-top: .1rem;
           }
         }
         >audio{
           position: absolute;
         }
         .progressWrap{
           height: .8rem;
           font-size: .24rem;
           line-height: .8rem;
           text-align: center;
           .current{
             width: 12%;
             float: left;
           }
           .progress{
             width: 70%;
             height: .1rem;
             display: inline-block;
             vertical-align: .03rem;
             border-radius: .05rem;
             background-color: darken(@color-white,10%);
             position: relative;
             .time-line{
               position: absolute;
               height: 100%;
               border-radius: .05rem;
               background-color: @color-green;
             }
           }
           .duration{
             width: 12%;
             float: right;
           }
         }
         .download{
           width: 4.9rem;
           height: 1rem;
           line-height: 1rem;
           font-size: .36rem;
           margin: 0 auto;
           border-radius: .5rem;
           background-color: darken(@color-green,2%);
           text-align: center;
           position: relative;
           &::after{
             position: absolute;
             width: .74rem;
             height: .74rem;
             top: 50%;
             left: .16rem;
             margin-top: -.37rem;
             content: "";
             .spriteFn2();
           }
           >a{
             color: @color-white;
             font-weight: 700;
           }
         }
       }
      
    • JS代码:
       //添加拉伸事件
       $(window).on("resize",resizeTo).trigger("resize");
       var $htmlFont;
       function resizeTo() {
           //计算不同屏幕下html的fontSize值
           var $screenWidth=$(window).width();
           var $sjWidth=640;
           var $sjFont=100;
           //当屏幕宽度大于640px时,让$screenWidth值为640px,则计算出来的fontSize值一直为100px;
           //保证了屏幕中的rem值稳定,不会再随着屏幕改变而改变;
           if($screenWidth>$sjWidth){
               $screenWidth=$sjWidth;
               $("html").css({
                   width:$sjWidth,
                   margin: "0 auto"
               });
           }
           $htmlFont=$screenWidth/$sjWidth*$sjFont;
           $("html").css("fontSize",$htmlFont);
           //1 计算不用屏幕下的main歌词区域的高度
           //注意:在jQuery中$().height()拿到的高度不包含padding和边框,而zpeto中包含;
           //在jQuery中用$().outerHeight()可以拿到包含padding和边框的高度,但是zpeto中不支持此属性;
           var $screenH=$(window).height();
           var $mainH=$screenH-$("header").height()-$("footer").height()-0.8*$htmlFont-0.6*$htmlFont;//jQuery引入后,会覆盖zpeto;
           $(".main").css("height",$mainH);
       }
       //2 获取后台歌词数据,转换成需要的格式通过订阅式发布输出;
       var data=[],
           $id=0;
       //ajax获取数据,经过转化后,获取数组,然后通过jQuery中的订阅发布传入数据;
       var musicRender=(function () {
           return {
               init:function () {
                   $.ajax({
                       url:"data/lyc.txt",
                       dataType:"text",
                       type: "get",
                       success: function (result) {
                           var ary=result.split("\\n");//\n需要转义符,将获取的字符串数据,分割为数组;
                           var reg=/\[(\d{2})\:(\d{2})\.(?:\d{2})\](\D+)/g;//通过小分组拿到分,秒,文字;
                           //forEach方法,遍历数组,第一项为数组元素内容,第二项为数组元素的索引值
                           ary.forEach(function (item,index) {
                               //item为每一项的字符串,通过replace方法配合正则,进行逐一匹配操作;
                               item.replace(reg,function () {
                                   data.push({
                                       minute:arguments[1],
                                       seconds: arguments[2],
                                       lyc:arguments[3],
                                       id:$id
                                   })
                               });
                               $id++;
                           });
                           callbacks.fire(data);//向订阅发布传入数据
                       }
                   })
               }
           }
       })();
       musicRender.init();
       
       //3 jQuery中的订阅发布,获取歌词数据,插入页面
       var callbacks=$.Callbacks(),
           $lyc=$(".main .lyc"),
           $current=$("footer .progressWrap .current"),
           $duration=$("footer .progressWrap .duration");
       //获取媒体变量
       var oAudio=$("audio")[0],
           $btn=$(".h-right"),
           $hr_play=$(".hr-play"),
           $hr_pause=$(".hr-pause");
       //获取定时器变量
       var timer=null;
       //获取进度条元素
       var $time_line=$(".progress .time-line");
       //订阅式绑定方法;获取传入的数据,绑定在页面中;
       callbacks.add(function (data1) {
           //此时获得的数据为原生数组
           var str="";
           $.each(data1,function (index, item) {
               //字符串拼接,将数据放在自定义属性上;
               str+=`<p data-minute="${item.minute}" data-seconds="${item.seconds}">${item.lyc}</p>`
           });
           $lyc.html(str);
       });
       //创建函数,用于转化时间格式
       function timeFormat(time){
           var min=Math.floor(time/60);//分钟用向下取整;
           var sec=Math.ceil(time%60);//秒用向上取整;这样会让歌词比音乐快一些;
           //判断当秒数为60时,变为0,分钟加等1;
           if(sec===60){
               sec=0;
               min+=1;
           }
           min=min<10?"0"+min:""+min;//字符串拼接;得到的是字符串;
           sec=sec<10?"0"+sec:""+sec;
           return min+":"+sec;
       }
       //4 进入页面歌曲播放;获取音频的当前时间,控制歌词更新
       callbacks.add(function () {
           oAudio.play();//加载页面后,歌词立刻播放;
           //拿到当前音频对象的总时间,为总秒数;转化格式后赋给$duratoin
           oAudio.addEventListener("canplay",function () {
               $duration.html(timeFormat(oAudio.duration));
               /*oAudio.addEventListener("timeupdate",fn1)//每隔0.3s触发一次,可以替换定时器;*/
               timer=setInterval(fn1,1000);//开启定时器,不断获取新的currentTime
           })
       });
       function fn1() {
           //获取当前的音乐时间,赋值在$current中;
           var currentTime=timeFormat(oAudio.currentTime);
           $current.html(currentTime);
           //通过获取的当前时间值,进行筛选p元素身上的自定义属性;进而控制相对应的文字变色显示;
           var minute=currentTime.split(":")[0];
           var seconds=currentTime.split(":")[1];
           //利用filter过滤器,通过属性判断,过滤选择;
           var targetP=$lyc.children("p").filter(`[data-minute="${minute}"]`).filter(`[data-seconds="${seconds}"]`);
           //将获取的p添加active类名;其他的兄弟元素删除类名;
           targetP.addClass("active").siblings().removeClass("active");
           //歌词的移动,通过给lyc添加定位,控制其top值的变化
           var indexP=targetP.index();//通过索引值获取哪个p的时候,开始运动;
           if(indexP>=2){
               $lyc.css("top",-(indexP-2)*0.84*$htmlFont);
           }
           //进度条的设置:设置time-line的宽度占progress的宽度百分比
           var tlW=Number(oAudio.currentTime/oAudio.duration*100)+"%";
           //$time_line.css("width",tlW);
           $time_line.animate({
               width: tlW
           });
           //当前时间等于总时间时,停止定时器,按钮变为pause;
           if(oAudio.currentTime===oAudio.duration){
               clearInterval(timer);
               oAudio.pause();
               $hr_pause.show();
               $hr_play.hide();
           }
       }
       //5 播放和暂停的制作;
       callbacks.add(function () {
           $btn.on("click",function () {//在移动端不添加click时间,添加tap事件
               clearInterval(timer);
               //在音频play播放时,oAudio.paused返回false值;
               if(oAudio.paused){
                   fn1();
                   timer=setInterval(fn1,1000);
                   oAudio.play();
                   $hr_play.show();
                   $hr_pause.hide();
               }else{
                   oAudio.pause();
                   $hr_pause.show();
                   $hr_play.hide();
               }
           })
       });
      

    相关文章

      网友评论

        本文标题:第十三周之QQ音乐移动端项目实战代码

        本文链接:https://www.haomeiwen.com/subject/uodnfqtx.html