用Vue做一个播放器

之前在B站上面看到一个视频:

https://www.bilibili.com/video/BV1Yz411z7An?t=16

感觉它的这个播放器挺好看的,原作者是用的PPT制作。

我的设计灵感一向很差,叫我自己设计UI一般会非常难看,于是就准备仿照他这个,用Vue通过web的形式,参照他的界面,做一款播放器玩玩。

img

目标

制作一个简单的播放器,拥有播放,暂停,上一首,下一首,歌曲列表等功能。音乐数据就通过axios从我的后端服务器上面取得。

准备

既然有了目标,那么首先就需要创建一个Vue工程:

vue create music_player

注意:Vue的工程名称不能包含大写,但是可以有下划线。

因为是复刻嘛,想要做到完全一样难度还是比较大的,所以就大概相似就差不多了,我就使用Vant作为UI。

Vant UI - 快速上手youzan.github.io

该工程一看就是一个手机版的播放器,所以我还引入了rem文件:

(function (doc, win) {
  const docEl = doc.documentElement;
  const resizeEvt = 'orientationchange' in window ? 'orientationchange' : 'resize';
  const recalc = function () {
    const { clientWidth } = docEl;
    if (!clientWidth) return;
    docEl.style.fontSize = `${100 * (clientWidth / 375)}px`;
  };
  if (!doc.addEventListener) return;
  win.addEventListener(resizeEvt, recalc, false);
  doc.addEventListener('DOMContentLoaded', recalc, false);
}(document, window));

该文件是为了使页面自适应。该文件的意思是100px0.1rem,所以我们之后使用的所有px都要换算成为rem

调试模式

img

因为主要是做的移动端的项目,所以需要将浏览器的调试模式设置为iPhone 6/7/8,这也是现在移动端开发最为主流的分辨率。但是后面我将模式切换到了iPhone X…因为iPhone 6模式下整个界面显得有点拥挤。

搭建界面

搭建界面几乎没有什么难度,CSS样式需要一点点的慢慢调整,最后调整到合适的样式。

img

img

先简单的搭出一个界面,等到跑通业务逻辑后,我们再来进行微调。

Vuex

这种播放器之间的数据传递还是需要使用Vuex如果单靠组件之间的单向传递,那可是太麻烦了。

img

从这里开始我将调试模式改为了iPhone X

我放入Vuex管理的数据有:

state: {
  /* 歌曲列表 */
  musicList: [{
    id: 0, // 歌曲id
    musicName: '',// 歌曲名字
    musicSinger: '',// 歌手名字
    musicImg: '',// 歌曲图片
    musicUrl: '',// 歌曲地址
  }],
  /* 音乐是否在播放 */
  musicStatus: false,
  // 当前播放的音乐
  musicIndex: 0,
  // 管理音乐
  music: {
    play: Function,
    pause: Function,
  },
},

可以看到,集成Vuex后这些数据进行了正常显示,并且点击右下角的播放按钮,歌曲也能进行播放。

放到Vuex进行管理有个最大的好处就是,所有数据都只存在一份,如果一旦一个地方改变了数据,那么其它引用该数据的地方都会进行改变,比如:

img

可以看到,在第二个界面改变了数据后,第一个界面也发生了变化

剩下的就是播放动画了。

音乐频率图

img

由于最开始创建项目的时候我勾选了sass,所以这个音乐频率图用sass来做是十分快捷的。

/* 声明动画 */
@keyframes move {
  from {
    transform: translateY(0);
  }
  to {
    transform: translateY(50px);
  }
}


/* 因为上面有70个div所以这里就用sass的循环,如果是css就只有一个一个的添加 */
@for $i from 1 through 70 {
  &:nth-child(#{$i}) {
    /* 使用随机数声明 */
    animation: move linear 0.5s ((random(1000)-500)/1000+s) infinite alternate;
  }
}

最后微调

最主要是将开始的字体,行距,居中显示这些内容进行优化,因为开始只是大概的搭了一个界面后就先去做业务逻辑部分了,所以页面中还是有很多需要优化的地方。

img

进度条优化

根据音乐当前播放时间和总时间,计算出音乐进度,将小于这个值的进度条都附加上一个更换背景颜色的类。

<div v-for="(i,index) in 40" :key="index"
     :class="`hight ${musicPlay?'anima':''} ${progress>index?'progress':''}`">
</div>

.progress {
  background: #123a70;
}

计时器

this.timer = setInterval(() => {
  this.progress = Math.floor((this.musicTime / this.music) * 40);
  console.log(this.progress);
}, 1000);

// 页面销毁后销毁定时器
destroyed() {
  clearInterval(this.timer);
},

因为播放进度是通过setInterval每秒钟进行计算,所以计时器一定要在页面被销毁的时候一起给销毁掉,不然计时器会越来越多。

总结

整个播放器的制作不难,难点在于Vuex的使用,该项目里面可能会有很多隐藏的BUG,或者体验不佳的地方,因为只做了个大概,没有太在意细节部分,如果一个项目要上线还是要经过不断的测试优化。