亚洲激情专区-91九色丨porny丨老师-久久久久久久女国产乱让韩-国产精品午夜小视频观看

溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務條款》

vue-music關于Player播放器組件詳解

發布時間:2020-08-31 09:05:14 來源:腳本之家 閱讀:188 作者:ankle 欄目:web開發

本文實例為大家分享了關于Player播放器組件的具體內容,供大家參考,具體內容如下

vue-music關于Player播放器組件詳解

迷你播放器:

vue-music關于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實戰教程》

以上就是本文的全部內容,希望對大家的學習有所幫助,也希望大家多多支持億速云。

向AI問一下細節

免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。

AI

大埔区| 崇文区| 历史| 鲁山县| 黔南| 富裕县| 永修县| 沈阳市| 年辖:市辖区| 成都市| 高唐县| 榆林市| 信丰县| 固原市| 许昌市| 清远市| 黄大仙区| 平舆县| 叙永县| 特克斯县| 牡丹江市| 甘德县| 辛集市| 公主岭市| 南昌县| 民权县| 英山县| 九江县| 东乌珠穆沁旗| 东海县| 黄大仙区| 万宁市| 寿光市| 汾西县| 永昌县| 江川县| 平和县| 油尖旺区| 松滋市| 永靖县| 庐江县|