播放器内置组件开发
播放器可以通过歌手详情列表、歌单详情列表、排行榜列表以及搜索结果打开,换言之,多个组件都可以操作这个播放器。
播放器Vuex数据设计
打开播放器时点击缩小播放器仍然可以在后台播放运行,也就是说全局性的控制播放器数据,所以要通过vuex管理 。首先思考播放器需要哪些相关数据。
列出播放器相关的数据:
playing:播放状态
fullScreen:展开或收起
playlist:播放列表
sequenceList:顺序列表
mode:播放模式
currentIndex:当前播放索引
state.js
|
|
这几个数据的其他配置如mutations、getters在此省略,具体参考代码。
播放器组件开发
播放器player.vue 基础样式
|
|
播放器是全局组件,放在App.vue下面,通过Vuex传递数据,触发action提交mutation,从而使播放器开始工作。
App.vue
|
|
用vuex相关数据控制播放器的显示和隐藏,传入fullScreen控制显示或隐藏,playlist控制播放器渲染。
|
|
控制播放器的展示
点击歌曲列表时展开播放器,也就是点击歌曲列表song-list组件,给song-list组件添加事件selectItem(item, index)

而song-list又被music-list组件使用,在music-list组件触发select事件@select="selectItem"。
music-list.vue
|
|
selectItem要做三件事:
1、点击歌曲时要播放整个歌曲列表,设置playlist和sequenceList
2、根据点击的歌曲索引,设置currentIndex,点击时实际上歌曲要播放了,设置播放状态playing
3、默认展开全屏播放器,设置fullScreen
设置这些数据实际就是提交mutations。在一个动作中多次改变mutation那么会封装一个action。在actions.js里定义selectPlay。
action.js
|
|
selectPlay对一系列mutation做封装,提交mutation。
在music-list组件里调用actions
|
|
action逻辑执行mutation就会改变,mutation改变就会映射到mapGetters,也就会得到fullScreen和playlist的改变。

通过定义的vuex以及一些事件点击操作去修改的vuex数据,这些操作行为成功实现了player组件的显示。
传入currentSong填充歌曲基本数据
|
|
效果展示:

mini播放器的展示
miniPlayer是需要把fullScreen设置为false,因此点击返回按钮时把fullScreen设置为false,添加个click事件。
|
|
通过mutation改变fullScreen。
效果展示:

点击mini播放器打开全屏,同理在mini播放器添加个click事件
|
|
播放器展开收起动画
最大化和最小化切换
播放器最大化和最小化切换时没有交互动画显得比较生硬,为了体验更好使用<transition></transition>自定义标签设置交互动画。

使用<transition></transition>包裹要实现的区块。然后根据name编写css样式

点击放大或缩小时的交互动画
当展开收起播放器时,mini播放器的图片放大或缩小有渐变的效果,利用vuejs提供JavaScript钩子,在钩子里创建css3的animation。给name为normal的添加@enter、@afterEnter、@leave、@afterLeave这几个事件。

enter方法有两个参数,第一个参数el是要做动画的dom,第二个参数done是回调函数,done执行时就会跳到下一个钩子afterEnter,leave和enter一样有两个参数,done执行时跳到下个钩子afterLeave。
使用css3写动画首先要知道几个位置:从运动的起始点和终点的区域、横坐标和纵坐标以及scale的大小。但这些是动态获取的不能预先知道,所以通过js的方式创建css3动画。这里使用create-keyframe-animation第三方库实现通过js编程方式创建css3动画。
在这之前先封装个函数来获取初始位置
|
|
点击目标创建动画
|
|
动画执行完后调用done函数,done函数执行后跳到afterEnter,afterEnter做的事情就是结束动画,animation设置为空
|
|
leave动画
|
|
leave动画执行完后调用done,done执行完后跳到afterLeave,afterLeave将动画设置为空
|
|
播放器歌曲播放功能实现
播放功能实际上是使用HTML5的audio标签实现的,src属性指向的是播放音乐地址。
在player.vue里添加audio标签
|
|
仅仅通过指定播放地址是不能播放,还需要调用audio的play方法,在currentSong发生改变时调用play方法,这样要watch currentSong的变化
|
|
启动效果会报错:
|
|
这是dom异常,在调用play方法时同时去请求src,但dom还没被读取就调用play,所以报错了。在这加个延迟$nextTick()
|
|
报错消失,歌曲正常播放。
音乐暂停功能实现
vuex里有定义一个状态叫playing,是控制当前播放歌曲是播放还是暂停状态。点击歌曲列表时会提交一个action,在action里提交SET_PLAYING_STATE的mutation设置为true,所以当点击歌曲列表时playing状态为true。通过mapGetters里的playing获取当前状态,然后通过mutation改变playing的状态
|
|
调用setPlayingState方法改变playing状态
|
|
仅仅设置playing不能让播放器停止,真正控制播放的还是播放器,所以watch playing状态
|
|
动态改变播放按钮样式
当点击歌曲播放时显示播放按钮,点击暂停时显示暂停按钮。
|
|
同理,mini播放器也是
|
|
点击mini播放器播放按钮发现播放器又弹了出来,是因为子元素点击事件会冒泡到父元素上,父元素也有个点击事件去打开播放器,为了防止事件向上冒泡修改为@click.stop='togglePlaying'。
|
|
cd图片旋转
歌曲播放时歌曲图片跟着旋转,暂停时图片不动
|
|
同理,mini播放器也是
|
|
歌曲前进后退功能实现
前进后退功能其实就是改变当前播放歌曲的索引。
vuex有个状态是currentIndex,表示当前播放歌曲的索引,当点击歌曲列表时触发action,action有个对SET_CURRENT_INDEX的mutation的提交,修改currentIndex播放到第几位,这也代表了当前播放的歌曲。通过mapGetters里的currentIndex获取当前播放歌曲,然后通过mutation改变currentIndex。
|
|
添加@prev和@next方法
|
|
点击暂停切换下首歌,下首歌播放了但icon没发生变化,是因为点击next时歌曲切换了但是playing状态没修改,这里修改下代码。
|
|
快速切换歌曲时会报Uncaught (in promise) DOMException: The play() request was interrupted by a new load request.之前遇到的错误。
audio有@canplay和@error两个事件:
1、@canplay:当歌曲加载播放会触发事件,
2、@error:当歌曲地址发生错误时会触发error事件
在audio标签监听@canplay="read"和@error="error"事件
|
|
只有当歌曲read时才能点击下首歌,反之不能点击下首歌。用一个标识位控制,在data里定义songReady。
|
|
当用户切换下首歌遇到网络错误或者下首歌url错误,songReady永远不能执行,之后的点击事件都不能用,当下首歌加载失败触发error函数
|
|
从样式上做些处理,当我们不能点击时给这个按钮绑定disableClas
|
|
