您好,登錄后才能下訂單哦!
本文實例為大家分享了關于Player播放器組件的具體內容,供大家參考,具體內容如下
迷你播放器:
1.播放器組件會在各個頁面的情況下會打開。 首先在vuex state.js 中定義全局的播放器狀態
import {playMode} from 'common/js/config.js'; const state = { singer:{}, playing:false, //是否播放 fullScreen:false, //是否全屏 playList:[], //播放列表 sequenceList:[], // 非順序播放列表 mode:playMode.sequence, // 播放模式(順序0,循環1,隨機2) currentIndex:-1, //當前播放索引 } export default state --------------------------------------------- // config.js export const playMode = { sequence:0, loop:1, random:2 }
2.進入播放器頁面時獲取播放列表數據,改變播放狀態 在music-list列表中打開
在song-list 組件中派發事件到父組件,傳入當前歌曲的信息和索引
<li @click="selectItem(song,index)" v-for="(song,index) in songs" class="item"> ------------------------------ selectItem(item,index){ this.$emit('select',item,index) },
在music-list 組件中接受派發事件。
<song-list :rank="rank" :songs="songs" @select="selectItem"></song-list>
3. 如果commit 多個狀態在actions 里設置
import {playMode} from 'common/js/config.js' export const selectPlay = function({commit,state},{list,index}){ commit(types.SET_SEQUENCE_LIST, list) commit(types.SET_PLAYLIST, list) commit(types.SET_CURRENT_INDEX, index) commit(types.SET_FULL_SCREEN, true) commit(types.SET_PLAYING_STATE, true) }
4. 在music-list 組件中 用mapActions提交 改變值
import {mapActions} from 'vuex' methods:{ selectItem(item,index){ this.selectPlay({ list:this.songs, index }) }, ...mapActions([ 'selectPlay' ]) },
5.在palyer 中獲取vuex 全局狀態,賦值狀態到相應位置(代碼為完整代碼,對照后面講解慢慢理解)
<div class="player" v-show="playList.length>0"> // 如果有列表數據則顯示 <div class="normal-player" v-show="fullScreen"> //如果全屏 <div class="background"> <img :src="currentSong.image" alt="" width="100%" height="100%"> //模糊背景圖 </div> <div class="top"> <div class="back" @click="back"> <i class="icon-back"></i> </div> <h2 class="title" v-html="currentSong.name"></h2> //當前歌曲名稱 <h3 class="subtitle" v-html="currentSong.singer"></h3> //當前歌手名 </div> <div class="middle"> <div class="middle-l"> <div class="cd-wrapper"> <div class="cd" :class="cdCls"> <img :src="currentSong.image" alt="" class="image"> //封面圖 </div> </div> </div> </div> <div class="bottom"> <div class="progress-wrapper"> <span class="time time-l">{{ format(currentTime) }}</span> <div class="progress-bar-wrapper"> <progress-bar :percent="percent" @percentChange="onProgressBarChange"></progress-bar> </div> <span class="time time-r">{{ format(currentSong.duration) }}</span> </div> <div class="operators"> <div class="icon i-left"> <i :class="iconMode" @click="changeMode"></i> </div> <div class="icon i-left" :class="disableCls"> <i @click="prev" class="icon-prev"></i> </div> <div class="icon i-center" :class="disableCls"> <i :class="playIcon" @click="togglePlaying"></i> </div> <div class="icon i-right" :class="disableCls"> <i @click="next" class="icon-next"></i> </div> <div class="icon i-right"> <i class="icon icon-not-favorite"></i> </div> </div> </div> </div> </transition> <transition name="mini"> <div class="mini-player" v-show="!fullScreen" @click="open"> <div class="icon"> <img :src="currentSong.image" alt="" width="40" height="40" :class="cdCls"> </div> <div class="text"> <h3 class="name" v-html="currentSong.name"></h3> <p class="desc" v-html="currentSong.singer"></p> </div> <div class="control"> <i :class="miniIcon" @click.stop="togglePlaying"></i> </div> <div class="control"> <i class="icon-playlist"></i> </div> </div> </transition> <audio :src="currentSong.url" ref="audio" @canplay="ready" @error="error" @timeupdate="updateTime" @ended="end"></audio> </div>
打開播放器的狀態
import {mapGetters,mapMutations} from 'vuex'; ...mapGetters([ 'fullScreen', 'playList', 'currentSong', 'playing', 'currentIndex', ])
注意:不可在組件中直接賦值改版vuex 中的狀態 this.fullScreen = false 需要通過mutations 改變,定義mutation-types 和mutations 然后 用vuex的 mapMutations 代理方法調用
[types.SET_FULL_SCREEN](state, flag) { state.fullScreen = flag }, import {mapGetters,mapMutations} from 'vuex'; methods:{ ...mapMutations({ setFullScreen:"SET_FULL_SCREEN", }), back(){ this.setFullScreen(false) }, }
設置點擊播放按鈕方法
<i :class="playIcon" @click="togglePlaying"></i>
togglePlaying(){ this.setPlayingState(!this.playing); //改變全局變量playing 的屬性 }, // 然后watch 監聽playing 操作實際的audio 標簽的播放暫停 watch:{ playing(newPlaying){ let audio = this.$refs.audio; this.$nextTick(() => { newPlaying ? audio.play():audio.pause(); }) } }, // 用計算屬性改變相應的播放暫停圖標 playIcon(){ return this.playing? 'icon-pause':'icon-play' },
設置點擊播放上一首和下一首按鈕方法。用mapGetters 獲取currentIndex 的值(加一或減一) 并改變,從而改變 currentSong 的狀態,監聽切換播放。判斷播放列表界限重置。
prev(){ if(!this.songReady){ return; } let index = this.currentIndex - 1; if(index === -1){ //判斷播放列表界限重置 index = this.playList.length-1; } this.setCurrentIndex(index); if(!this.playing){ //判斷是否播放改變播放暫停的icon this.togglePlaying(); } this.songReady = false; }, next(){ if(!this.songReady){ return; } let index = this.currentIndex + 1; if(index === this.playList.length){ //判斷播放列表界限重置 index = 0; } this.setCurrentIndex(index); if(!this.playing){ this.togglePlaying(); } this.songReady = false; },
監聽audio 元素標簽的canpaly 事件,當歌曲加載就緒 和 error 事件,當歌曲發生錯誤的時候,做用戶體驗,防止用戶快速切換導致報錯。
設置songReady 標志位 如果歌曲沒有準備就緒,點擊下一首的時候直接return false
data(){ return { songReady:false, } }, ready(){ this.songReady = true; }, error(){ this.songReady = true; },
進度條
audio元素監聽 timeupdate 事件獲取當前播放時間的 可讀寫屬性 時間戳。用formt做格式化時間處理,(_pad 為補零函數 )
獲取音頻總時長 currentSong.duration
<div class="progress-wrapper"> <span class="time time-l">{{ format(currentTime) }}</span> <div class="progress-bar-wrapper"> <progress-bar :percent="percent" @percentChange="onProgressBarChange"></progress-bar> </div> <span class="time time-r">{{ format(currentSong.duration) }}</span> </div> <audio :src="currentSong.url" ref="audio" @canplay="ready" @error="error" @timeupdate="updateTime" @ended="end"></audio>
updateTime(e){ this.currentTime = e.target.currentTime; // 獲取當前播放時間段 }, format(interval){ interval = interval | 0; const minute = interval/60 | 0; const second = this._pad(interval % 60); return `${minute}:${second}`; }, _pad(num,n=2){ let len = num.toString().length; while(len<n){ num = '0' + num; len ++; } return num; },
建立progress-bar 組件 接收pencent 進度參數,設置進度條寬度和小球的位置。player組件 設置計算屬性percent
percent(){ return this.currentTime / this.currentSong.duration // 當前時長除以總時長 },
progress-bar 組件
<div class="progress-bar" ref="progressBar" @click="progressClick"> <div class="bar-inner"> <div class="progress" ref="progress"></div> <div class="progress-btn-wrapper" ref="progressBtn" @touchstart.prevent="progressTouchStart" @touchmove.prevent="progressTouchMove" @touchend="progressTouchEnd" > <div class="progress-btn"></div> </div> </div> </div>
const progressBtnWidth = 16 //小球寬度 props:{ percent:{ type:Number, default:0 } }, watch:{ percent(newPercent){ if(newPercent>=0 && !this.touch.initated){ const barWidth = this.$refs.progressBar.clientWidth - progressBtnWidth; const offsetWidth = newPercent * barWidth; this.$refs.progress.style.width = `${offsetWidth}px`; this.$refs.progressBtn.style.transform=`translate3d(${offsetWidth}px,0,0)` } } }
設置拖動
在進度條小按鈕progressBtn 上添加touchstart,touchmove,touchend 事件監聽方法,事件添加 prevent 防止拖動默認瀏覽器行為,獲取拖動的信息進行計算
在實例上創建一個touch 對象維護不同的回調之間的通訊共享狀態信息。 touchstart事件方法中 ,首先設置this.touch.initated為true,表示拖動開始。 記錄開始點擊位置 e.touches[0].pageX 存到 touch 對象上,記錄當前的進度寬度。
在touchmove 中首先判斷 是否先進入了 touchstart 方法,計算得到 移動的位置 減去 點擊開始的位置的 偏移量長度。 let deltax = e.touches[0].pageX - this.touch.startX
就可以 設置進度條 已有的長度加上偏移量長度。最大不能超過父級progressbar 的寬度
調用this._offset(offsetWidth) 方法設置進度條寬度
在touchend 事件方法中將 this.touch.initated 設置為false,表示拖動結束,并派發事件到player 組件將audio的currentTime 值設置為正確值,參數為pencent
在progressbar 中增加點擊事件,調用this._offset(e.offsetX),并且派發事件
created(){ this.touch = {}; }, methods:{ progressTouchStart(e){ this.touch.initiated = true; this.touch.startX = e.touches[0].pageX; this.touch.left = this.$refs.progress.clientWidth; }, progressTouchMove(e){ if(!this.touch.initiated){ return; } let deltaX = e.touches[0].pageX - this.touch.startX; let offsetWidth = Math.min(this.$refs.progressBar.clientWidth - progressBtnWidth,Math.max(0,this.touch.left + deltaX)); this._offset(offsetWidth); }, progressTouchEnd(e){ this.touch.initiated = false; this._triggerPercent(); }, progressClick(e){ const rect = this.$refs.progressBar.getBoundingClientRect(); const offsetWidth = e.pageX - rect.left; this._offset(offsetWidth); // this._offset(e.offsetX); this._triggerPercent(); }, _offset(offsetWidth){ this.$refs.progress.style.width = `${offsetWidth}px`; this.$refs.progressBtn.style[transform] = `translate3d(${offsetWidth}px,0,0)`; }, _triggerPercent(){ const barWidth = this.$refs.progressBar.clientWidth - progressBtnWidth; const percent = this.$refs.progress.clientWidth / barWidth; this.$emit("percentChange",percent) } },
本文已被整理到了《Vue.js前端組件學習教程》,歡迎大家學習閱讀。
關于vue.js組件的教程,請大家點擊專題vue.js組件學習教程進行學習。
更多vue學習教程請閱讀專題《vue實戰教程》
以上就是本文的全部內容,希望對大家的學習有所幫助,也希望大家多多支持億速云。
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。