輕量級音樂播放器搭建 4

輕量級音樂播放器搭建 4

 

繼續未完成的事業,仍是有這個錯誤:css

我不知道爲何,可能內部執行的就是有時間差吧。因此將play()函數手動進行延遲吧,我想使用setTimeout,一開始是這麼寫的。html

  watch: {
 currentMusicIndex: function (newVal, oldVal) {
   setTimeout(function () {
     console.log(this)
     this.$refs.audio.play()
  }, 200)
}
}

可是又有了新的問題:vue

  
Uncaught TypeError: Cannot read property 'audio' of undefined

這是由於在setTimeout中,this永遠指向window(能夠查看控制檯輸出this)。因此要在setTimeout以前得到this.$refs.audio。另外這個延遲應該有多少?我試了幾個值,感受不太好掌握,有很大一部分網絡的因素。能夠將watch中觀察currentMusicIndex修改以下:vuex

  
watch: {
 currentMusicIndex: function (newVal, oldVal) {
   let audioElement = this.$refs.audio
   setTimeout(function () {
     console.log('開始播放音樂')
     audioElement.play()
  }, 20)
}
}

或者就直接不用觀察currentMusicIndex這個data,而是觀察currentMusicUrl,這樣就沒有這麼多事情了。由於必定會保證先變化url,再進行歌曲的播放。因此watch修改以下:api

  
watch: {
 currentMusicUrl: function (newVal, oldVal) {
   let audioElement = this.$refs.audio
   setTimeout(function () {
     console.log('開始播放音樂')
     audioElement.play()
  }, 20)
}
}

其中我仍是加上了setTimeout,我投降,老是報錯那個no support source的錯誤。也許模板在渲染的速度要比腳本中代碼執行的慢一些。總之,添加一個延遲調用。網絡

而後還有一個就是展現歌曲專輯封面。這個我想能夠綁定或者與play()函數寫在一塊兒。由於專輯圖片展現的過程就是歌曲播放的過程,歌曲進行切換的時候,專輯圖片也要進行切換。因此對模板中圖片的src進行如下綁定,新建data屬性currentMusicPictureSrc表示專輯圖片的src地址。能夠找到src就是下圖中的地址:ide

picUrl或者是blurPicUrl均可以,這兩個是同樣的。如今的music-player.vue文件是這個樣子的:svg

  <template>
 <div class="music-player">
   <header-bar></header-bar>
   <div class="mid">
     <audio :src="currentMusicUrl" autoplay @ended="_playDefaultMusic(currentMusicIndex)" ref="audio"></audio>
     <img :src="currentMusicPictureSrc" class="music-album-picture">
   </div>
   <music-controller></music-controller>
 </div>
</template>


<script>
 import HeaderBar from 'components/header-bar/header-bar'
 import MusicController from 'components/music-controller/music-controller'
 import getDefaultMusicList from 'api/getDefaultMusicList'
 import {getMusicUrl} from 'api/playThisMusic'

 export default {
   data () {
     return {
       defaultMusicList: [],
       currentMusicUrl: '',
       currentMusicIndex: 0,
       currentMusicPictureSrc: '',
    }
  },
   components: {
     HeaderBar,
     MusicController
  },
   created () {
     console.log('MusicPlayer Created')
     this._getDefaultMusicList()
  },
   methods: {
     _getDefaultMusicList () {
       console.log('執行對默認歌單請求')
       getDefaultMusicList()
        .then((res) => {
           if (res.code === 200) {
             this.defaultMusicList = res.result
             console.log('獲取到默認歌單:')
             console.log(this.defaultMusicList)
          } else {
             console.log(res.code + '---未得到默認歌單數據')
          }
        })
        .then(() => {
           this._playDefaultMusic()
        })
    },
     _playDefaultMusic () {
       if (this.currentMusicIndex === this.defaultMusicList.length - 1) {
         this.currentMusicIndex = 0
      } else {
         this.currentMusicIndex = this.currentMusicIndex + 1
      }
       getMusicUrl(this.defaultMusicList[this.currentMusicIndex].id)
        .then((res) => {
           console.log('開始獲取歌曲 ' + this.defaultMusicList[this.currentMusicIndex].name + ' 播放地址')
           this.currentMusicUrl = res.data[0].url
           console.log('獲取到歌曲播放地址爲 ' + this.currentMusicUrl)
        })
    }
  },
   watch: {
     currentMusicUrl: function (newVal, oldVal) {
       let audioElement = this.$refs.audio
       console.log('切換專輯封面')
       this.currentMusicPictureSrc = this.defaultMusicList[this.currentMusicIndex].song.album.picUrl
       setTimeout(function () {
         console.log('開始播放音樂')
         audioElement.play()
      }, 20)
    }
  }
}
</script>


<style scoped>
 .music-player {
   width: 100%;
   height: 100%;
   background-color: cornsilk;
}
 .mid {
   width: 100%;
   height: 62%;
   display: flex;
   justify-content: center;
   align-items: center;
}
 .music-album-picture {
   width: 72%;
   height: auto;
   border-radius: 50%;
}
</style>

而後界面如今大致以下:函數

作完了這一個小功能,我想先停一下播放控制的邏輯編寫。而是對界面尤爲是播放控制界面先進行大致的編寫。由於若是沒有播放控制界面就編寫播放控制邏輯的話會很難以調試。佈局

因此下面的內容是在music-controller.vue中進行修改。

控制內容主要就是播放進度,上一首歌、下一首歌切換,喜歡此歌曲,暫停、播放切換,顯示歌詞等功能。主要的佈局參考網易雲音樂與老版豆瓣FM。對於切回上一首歌功能,我以爲既然是FM,網易雲音樂與豆瓣FM都不支持這個功能。可是本身在使用的時候,常常是不斷地切歌直到遇到本身想聽的歌,可是每每順手把想聽的歌也切過去了,就很煩。因此我感受能夠保留5歌點擊按鈕。從左到右分別是:

  1. 切換歌曲播放模式或者點擊喜歡這首歌。若是是在FM模式中,那麼就無所謂播放模式,可是能夠點擊紅心喜歡這首歌。若是是播放本地的(用戶私人的)列表,那麼也就不存在喜歡這首歌,而是切換播放模式。播放模式包括單曲循環播放、列表順序播放與列表隨機播放。

  2. 切換到上一首歌。這個功能須要有一個容器來儲存已經播放過的歌曲的列表。也有一個隱藏的條件是到了列表最開始的一首歌的時候則不能再向前切換歌曲。

  3. 暫停、播放切換。

  4. 切換到下一首歌。

  5. 歌曲詳情信息。包括歌曲的歌手、專輯、圖片等等,還有可能有評論。

另外有個播放進度控制,這個以後再說。如今還有個問題就是這些按鈕的圖片資源從哪裏找。我想是使用字體圖片。從阿里巴巴的矢量圖標庫上找了幾個,單個看都還行,但是合起來就不配套,先湊合着用吧:

這個矢量圖庫的使用方法在參考連接中有介紹。選擇好圖片以後,就能夠生成圖片連接。而後把unicode中的那一段css代碼複製到本身項目中對應組件的的style裏面。而後再從這個css中定義字體圖標通用樣式。以後就能夠在模板中使用這個字體圖標了,在想要顯示的地方插入一個class爲iconfont的i標籤,其中的內容就是網頁上圖標下邊的unicode碼。以下:

  
<template>
 <div class="music-controller">
  新垣結衣的播放控制器
   <div class="control-panel">
     <i class="iconfont danqu" >&#xe620;</i>
     <i class="iconfont liebiao">&#xe6f2;</i>
     <i class="iconfont suiji">&#xe6f1;</i>
     <i class="iconfont xin">&#xe6ca;</i>
     <i class="iconfont shangyishou">&#xe600;</i>
     <i class="iconfont bofang">&#xe768;</i>
     <i class="iconfont zanting">&#xe602;</i>
     <i class="iconfont xiayishou">&#xe601;</i>
     <i class="iconfont xiangqing">&#xe64d;</i>
   </div>
 </div>
</template>


<script>
 export default {}
</script>


<style scoped>
 @font-face {
   font-family: 'iconfont';  /* project id 431442 */
   src: url('//at.alicdn.com/t/font_431442_ylcevnla67xpqfr.eot');
   src: url('//at.alicdn.com/t/font_431442_ylcevnla67xpqfr.eot?#iefix') format('embedded-opentype'),
   url('//at.alicdn.com/t/font_431442_ylcevnla67xpqfr.woff') format('woff'),
   url('//at.alicdn.com/t/font_431442_ylcevnla67xpqfr.ttf') format('truetype'),
   url('//at.alicdn.com/t/font_431442_ylcevnla67xpqfr.svg#iconfont') format('svg');
}
 .iconfont {
   font-family:"iconfont";
   font-size:24px;
   font-style:normal;
}
 .music-controller {
   width: 100%;
   height: 30%;
   background-color: darkcyan;
}
</style>

如今是把template中的全部可能的icon或者說按鈕都放進去了,可是他們不是同時出現的。根據v-if與v-show的區別,參考播放器使用的場景,我認爲這裏使用v-show來控制這幾個圖標的顯示與否比較好。因此這裏就須要歌曲的狀態管理,從而要使用到vuex(其實以前歌曲播放那裏就可使用vuex)。若是不用vuex也能作,寫起來麻煩,耦合度高。關於vuex的內容晚上再說。

 

參考連接:

  1. setTimeout this

  2. 阿里巴巴矢量圖標庫

  3. 使用阿里巴巴圖標庫教程1

  4. 使用阿里巴巴圖標庫教程2

  5. v-if v-show 區別

相關文章
相關標籤/搜索