持续创作,加速生长!这是我参加「日新方案 10 月更文挑战」的第19天,点击检查活动详情

前语

很多小伙伴刚学完vue却没项目拿来操练?今日带你们制造一个归于自己的网易云音乐,经过操练加深自己的掌握,进步技术才能

预备工作

咱们需求用到vuex,vue-router,axios,better-scroll,element-ui,less,vue-lazyload,node.js,NeteaseCloundMusicApi;axios用来恳求数据,better-scroll用来歌词翻滚,element-ui组件库加速开发进度,less方便css代码编写,vue-lazyload用于图片懒加载,node.js搭建的本地测试服务器,NeteaseCloundMusicApi网易云音乐 NodeJS 版 API,供给音乐数据,下面是我下载的版本,能够对应我的版本装置

从0制造一个pc端网易云

咱们将网易云音乐 NodeJS 版 API下载下来到本地,终端node app.js运转,看到这一行代表运转成功了

主页

主页咱们运用elementui组件库的container布局容器,采用这一种布局:

从0制造一个pc端网易云

有相应的代码供咱们运用,咱们复制过来,给.el-container设置一个100vh的高度

<el-container>
    <el-header>Header</el-header>
    <el-container> 
        <el-aside width="200px">Aside</el-aside>
        <el-main>Main</el-main> 
    </el-container> 
</el-container>

el-header头部设置图标和搜索框,详细款式能够按自己想法来做,可是必需求设置一个搜索框用于搜索音乐

从0制造一个pc端网易云

el-aside里加入导航菜单组件,设置default-active绑定当时激活的菜单的页面,设置router运用 vue-router 的形式以 index 作为 path 进行路由跳转,给每个菜单设置index绑定路由完成点击菜单切换页面。

<el-menu
  :default-active="path"//默认激活页面
  background-color="#EDEDED"
  text-color="#939393"
  active-text-color="#DD6D60"
  :router="true"//敞开路由形式
>
<el-menu-item index="/discovery"> <!-- index路由的地址 -->
  <i class="iconfont icon-yinle1"></i>
  <span slot="title">发现音乐</span>
</el-menu-item>
<el-menu-item index="/playlists">
  <i class="iconfont icon-danlieliebiao"></i>
  <span slot="title">引荐歌单</span>
</el-menu-item>
<el-menu-item index="/songs">
  <i class="iconfont icon-yinle"></i>
  <span slot="title">最新音乐</span>
</el-menu-item>
<el-menu-item index="/mvs">
  <i class="iconfont icon-24gf-playSquare"></i>
  <span slot="title">最新MV</span>
</el-menu-item>
</el-menu>

最终给底部增加一个audio标签用于播映音乐

<div class="player">
  <!-- 歌曲图片 -->
  <div class="bg">
    <div v-if="this.songX.url" @click="showlyc">
      <span class="iconfont icon-xiangshang2 top"></span>
      <img :src="this.songX.url" alt="" />
    </div>
  </div>
  <!-- audio -->
  <audio
    id="music"
    ref="audio"
    @play="play"
    @pause="pause"
    @timeupdate="timeupdate"
    @ended="ended"
    :src="idd"
    controls
    autoplay
  ></audio>
</div>

ok,主页制造完结,大概姿态就是这样了:

从0制造一个pc端网易云

功用页

咱们将左边菜单的页面路由嵌套在主页里边,在页面右边的main区域里显现出菜单的页面,然后就能够完成菜单之间的页面跳转了

从0制造一个pc端网易云

从0制造一个pc端网易云

接下来就预备开端发现音乐菜单页的制造,发现音乐菜单页主要为咱们呈现轮播图,一部分的引荐歌单,最新音乐和最新mv,咱们能够从NodeJS 版 API的文档找到咱们需求恳求数据的地址,运用axios发送恳求获取轮播图获取数据,烘托在elemenui的 轮播图组件上

从0制造一个pc端网易云

//获取轮播图数据
getBanner().then((res) => {
    console.log(res);
    if (res.code != 200) return 
    this.banners = res.banners;
});

从0制造一个pc端网易云

从0制造一个pc端网易云

其他功用依据不同的接口获取数据烘托到页面上就行了,其他的页面也是同理

从0制造一个pc端网易云

从0制造一个pc端网易云

从0制造一个pc端网易云

从0制造一个pc端网易云

搜索页面

从0制造一个pc端网易云

播映音乐

获取音乐url咱们运用/song/url接口,依据传入的id获取音乐的url地址,将获取到的url地址保存到vuex里,在audio标签里动态绑定src为保存在vuex里的url即可播映音乐

从0制造一个pc端网易云

getSongUrl(id).then((res) => {
    // console.log(res);
    if (res.code != 200) return 
    let url=res.data[0].url
    this.$store.state.url=url
  });

歌词处理

获取音乐url的同时也要调用/lyric接口获取歌词,可是获取到的歌词不能直接烘托,咱们能够看到获取到的歌词数据是一个字符串,里边保存着每个时刻对应的歌词,咱们要将时刻和歌词分开,并且时刻要转为number

从0制造一个pc端网易云

说说完成的思路,其实每句歌词之间都有一个n换行符,咱们运用split(‘n’)将字符串切割成一个数组

let lycc = res.lrc.lyric; //获取歌词列表
let lyclist = lycc.split("n");//以换行来切割

然后观察时刻的格局,都是[xx:xx:xx]或[xx:xx:xxx]的格局,咱们能够运用正则来对数组每一项进行匹配,然后运用splice(1,-1)方法去掉[]这两个符号,再用split(‘:’)切割数组,将数组每一项转为number后相加,就得到了时刻

let re = /[d{2}:d{2}.d{2,3}]/; //匹配时刻
let lyc=[]
for (let i in lyclist) {
  if (lyclist[i]) {
    let date = lyclist[i].match(re); //匹配时刻
    console.log(date);
    date = date[0].slice(1, -1); //去除【】
    let timelist = date.split(":"); //以:切割
    let m = timelist[0];//分
    let s = timelist[1];//秒
    let time = parseFloat(m) * 60 + parseFloat(s); //核算时刻
  }
}

最终运用replace()方法匹配正则取出歌词,将歌词和时刻以数组的方式保存到一个数组里,存到vuex里

for (let i in lyclist) {
  if (lyclist[i]) {
    let date = lyclist[i].match(re); //匹配时刻
    console.log(date);
    date = date[0].slice(1, -1); //去除【】
    let timelist = date.split(":"); //以:切割
    let m = timelist[0];
    let s = timelist[1];
    let time = parseFloat(m) * 60 + parseFloat(s); //核算时刻
    let lrcitem = lyclist[i].replace(re, ""); //获取歌词
    lyc.push([time, lrcitem]);
    this.$store.state.lyc=lyc
  }
}

处理后的歌词

从0制造一个pc端网易云

歌词翻滚

歌词翻滚咱们需求用到better-scroll,better-scroll 最常见的应用场景是列表翻滚,better-scroll 是效果在外层 wrapper 容器上的,翻滚的部分是 content 元素。这儿要注意的是,better-scroll 只处理容器(wrapper)的榜首个子元素(content)的翻滚,其它的元素都会被疏忽

<div class="wrapper" ref="wrapper">
  <ul class="content">
    <li>...</li>
    <li>...</li>
    ...
  </ul>
  <!-- 这儿能够放一些其它的 DOM,但不会影响翻滚 -->
</div>

翻开歌词的时候延时100毫秒后创建bScroll对象

<!-- 歌词翻滚 -->
<div class="wrapper" ref="scrolls">
    <div class="contents">
      <div
        :class="['items', { item_actice: lycindex == index }]"
        v-for="(item, index) in lycs"
        :key="index"
      >
        {{ item[1] }}
      </div>
    </div>
</div>
//歌词显现
showlyc() {
  this.showl = !this.showl;
  setTimeout(() => {
    this.scroll = new BScroll(document.querySelector(".wrapper"));
    // console.log(this.scroll);
  }, 100);
},

创建完bScroll对象后怎么翻滚呢?刚刚的处理完的歌词数组里每一句歌词都有对应的时刻,咱们依据当时播映的时刻和数组里的时刻进行匹配,当时播映时刻大于当时歌词对应的时刻小于下一句歌词对应的时刻时运用bScroll对象里的scrollTo方法进行翻滚

动态绑定audio的timeupdate事件,每触发一次就判定是否进行翻滚

timeupdate(e) {
    let currentTime = e.target.currentTime;
    let lyc = this.lycs;
    for (let i = 0; i < lyc.length; i++) {
        if (lyc[i][0] < currentTime && currentTime < lyc[i + 1][0]) {
          this.lycindex = i;
          if (this.scroll) {
            this.$refs.scrolls.scrollTo(0, (this.lycindex - 6) * 40);//让当时播映歌词固定在中心
          }
        }
    }
},

从0制造一个pc端网易云

最终

由于时刻有限只做了基本的播映暂停。循环随机顺序播映,登录等等很多功用都没有完成,有爱好的小伙伴能够自己测验完成,源码我放在了gitee里,欢迎来访