如果一个音乐应用没有播放,那么这款应用就是没有灵魂的,这也是进阶系列的重点之一。
本章主要讲解播放页的需求和逻辑处理,以及全局歌单的实现。

# 播放页的整体思路
初始化应用的时候,没有播放入口(没有添加播放列表),需要添加播放列表才可播放。用户在进入到 album 歌单页面选择播放列表时进入到播放页面,并到列表存在 Vuex 中,歌曲列表都在全局,这样可以做到全局播放。并记录用户的行为数据,播放列表处在哪一首。
# 播放器的基本控制
- 播放:点击播放列表中的歌曲进行播放,播放时跳转播放界面,并显示歌曲信息。
- 停止:当歌曲正在播放时,点击歌曲播放界面下方的停止键,停止当前播放的歌曲。
- 上一曲:当前歌曲索引值减一,重新初始化加载音频数据,播放列表中上一首歌曲,如果索引值小于0,则索引值为列表长度减去一。
- 下一曲:当前歌曲索引值加一,重新初始化加载音频数据,播放列表中下一首歌曲,如果索引值大于列表长度,则索引值为0。
- 播放列表:点击弹出歌曲列表界面。
- 播放模式:随机,顺序,单曲,控制改变歌曲索引值,加载不同音频数据。
- 添加歌曲:插入播放列表中。
- 删除歌曲:从播放列表剔除歌曲。
# 音频 API
const bgAudioMannager = uni.getBackgroundAudioManager(); // 创建一个音频
bgAudioMannager.title = '致爱丽丝'; // 音频的标题(歌名)
bgAudioMannager.singer = '暂无'; // 音频的作者 (歌手)
bgAudioMannager.coverImgUrl = 'https://img-cdn-qiniu.dcloud.net.cn/uniapp/audio/music.jpg'; // 音频的封面(专辑海报)
bgAudioMannager.src = 'https://img-cdn-qiniu.dcloud.net.cn/uniapp/audio/music.mp3'; // 音频源 (mp3)
// 事件不用重复设定,只用在 onload 时初始化一次即可
backgroundAudioManager.onPlay() // 背景音频播放事件,判定播放状态
backgroundAudioManager.onPause() // 背景音频暂停事件,判定暂停状态
backgroundAudioManager.onTimeUpdate() // 背景音频播放进度更新事件,确定当前播放进度时间和底部滑块位置
backgroundAudioManager.onEnded() // 背景音频自然播放结束事件,播放完自动加载下一首歌曲
@前端进阶之旅: 代码已经复制到剪贴板
有上面 backgroundAudioManager 对象的方法和属性,就可以创建一个简单的播放器了,但是一个播放器有更多的交互,更新歌单,对应播放的歌曲,界面交互等效果,下面就来介绍网易云的播放器的效果与交互。
# 页面及样式的处理
这一块的样式效果主要是海报的虚化填充,磁盘的旋转动画,拨条机械臂的动画,以及进度滑块的使用。
1.背景虚化
<view class="play-page" :style="bgStyle">
<!-- 虚化蒙板 -->
<view class="bg"></view>
<!-- 内容层级在蒙板上 -->
<view class="content"></view>
</view>
// 最底层元素负责背景渲染,背景为行内样式
.play-page {
position: fixed;
right: 0;
left: 0;
width: 100%;
height: 100%;
background-position: center center;
background-repeat: no-repeat;
background-size: cover;
}
// filter 虚化最底层元素背景
.bg {
position: fixed;
z-index: 0;
right: 0;
left: 0;
height: 100%;
width: 100%;
filter: blur(40rpx);
background: inherit;
z-index:-1;
transform:scale(1.5);
}
@前端进阶之旅: 代码已经复制到剪贴板
- 磁盘转圈播放动画暂停以及重新开始旋转
主要的样式处理是磁盘转圈动画,以及拨条机械臂的滑动动画,监听音频播放停止事件,触发动画的运行。当点击开始按钮时候,就使用 css3 属性 transition 动画 transform 的旋转一定角度使得机械臂刚好落入到唱片磁盘内。当点击停止按钮时候,一方面控制唱片磁盘停止旋转,另一方面要操纵拨条机械臂匀速逆时针向上旋转离开唱片磁盘。 监听 playState 的变化,判定是否在播放状态。
<!-- 磁盘盒 -->
<view class="play-poster" @click="openList(0)">
<div class="poster-box" :class="playState ? '' : 'pause'">
<image class="img" v-if="curSongItem.picUrl" :src="curSongItem.picUrl"></image>
</div>
</view>
.play-poster {
margin: 310rpx auto 0;
.poster-box{
display: flex;
width: 616rpx;
height:616rpx;
margin: 0 auto;
background: url(https://s3.music.126.net/mobile-new/img/disc-ip6.png?69796123ad7cfe95781ea38aac8f2d48=) center center no-repeat;
background-size:100%;
align-items: center;
justify-content: center;
animation: circling 20s linear infinite;
// 播放停止下 animation 停止,旋转动画停止
&.pause{
animation-play-state: paused;
}
}
.img {
display: block;
margin: 0 auto;
width: 382rpx;
height: 382rpx;
border: solid 16rpx rgba(0, 0, 0, .15);
border-radius: 50%;