播放器播放模式有三种,顺序播放,单曲循环,随机播放,定义在vuex 中的字段为 mode。点击切换播放模式的图标。切换模式判断是否为随机播放,如果是随机播放模式,则取得sequenceList 列表数组 。
首先分清楚 sequenceList 是歌单顺序列表,显示在界面上的,playlist 是根据播放模式改变的,顺序播放时playlist 等于sequenceList ,随机播放时playlist 为随机数组列表
利用(shuffle)工具函数。将其随机打乱重组赋值给vuex中的playlist。当改变playlist的时候需要重置 currentIndex ,因为playlist改变为随机播放模式时。currentindex的索引指向的歌曲就不对了。 所以用 resetCurrentIndex 函数判断当前歌曲的id 是否和列表中播放的歌曲的id相同,相同则重新赋值该索引,保证在正在播放当前歌曲的时候切换模式,当前歌曲不被改变
// util.js
// 返回最小与最大值之间的随机数,包含最大最小值 function getRandomInt(min,max){ return Math.floor(Math.random() * (max - min+1) + min) } //将数组的副本循环随机打乱重组一个新数组返回 export function shuffle(arr){ let _arr = arr.slice(); for(let i=0;i<_arr.length;i++){ let j = getRandomInt(0,i); let t = _arr[i]; _arr[i] = _arr[j]; _arr[j] = t; } return _arr; }
vuex
export const playMode = { sequence:0, loop:1, random:2 } const state = { mode:playMode.sequence, } export default state
player.vue
<i :class="iconMode" @click="changeMode"></i> iconMode(){ return this.mode === playMode.sequence ? 'icon-sequence' : this.mode === playMode.loop ? 'icon-loop' : 'icon-random' //设置播放模式图标 }, changeMode(){ let mode = (this.mode + 1)%3; //点击循环切换 this.setPlayMode(mode); let list = null; if(mode === playMode.random){ list = shuffle(this.sequenceList) }else{ list = this.sequenceList; } this.resetCurrentIndex(list); //由于playlist 变成随机模式,currentsong是根据currentindex 和playlist 改变的,需要保持currentindex 在随机播放列表的正确位置,以确保当前播放歌曲不变 this.setPlayList(list); }, resetCurrentIndex(list){ let index = list.findIndex((item) => { return item.id === this.currentSong.id }) this.setCurrentIndex(index); },
单曲循环模式需要监听audio 元素ended 事件,如果end 时模式为loop模式,则设置当前歌曲的currentTime为0,并重新播放,否则按照播放列表进行下一首播放(播放列表此时有可能是顺序列表或者已改变为随机列表)
在music-list 组件中,点击随机播放按钮 提交actions 的randomPlay,设置playlist 为随机播放列表,在选择播放的时候判断当前播放模式
function findIndex(list,song){ return list.findIndex((item) => { return item.id === song.id; }) } export const selectPlay = function({commit,state},{list,index}){ commit(types.SET_SEQUENCE_LIST, list) if (state.mode === playMode.random) { let randomList = shuffle(list) commit(types.SET_PLAYLIST, randomList) index = findIndex(randomList, list[index]) } else { commit(types.SET_PLAYLIST, list) } commit(types.SET_CURRENT_INDEX, index) commit(types.SET_FULL_SCREEN, true) commit(types.SET_PLAYING_STATE, true) }
export const randomPlay = function({commit},{list}){ commit(types.SET_PLAY_MODE,playMode.random); commit(types.SET_SEQUENCE_LIST, list); let randomList = shuffle(list) commit(types.SET_PLAYLIST, randomList) commit(types.SET_CURRENT_INDEX, 0) commit(types.SET_FULL_SCREEN, true) commit(types.SET_PLAYING_STATE, true) }
<div class="play" ref="playBtn" @click="random"> random(){ this.randomPlay({ list:this.songs }) }, ...mapActions([ 'selectPlay', 'randomPlay' ])