播放器内置组件开发
播放器可以通过歌手详情列表、歌单详情列表、排行榜列表以及搜索结果打开,换言之,多个组件都可以操作这个播放器。
播放器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
|
|