讓工作與(vue)音樂相伴

盞茶作酒 流蘇如畫發表於2018-07-29

讓工作與(vue)音樂相伴

前言

最近在自學vue,打算自己仿一個專案來實戰一下,由於本人很喜歡聽歌,所以就選擇了網易雲音樂,在這與大家分享一下自己所遇到的問題,其中也有些不足之處也希望大家提一些寶貴的意見,互相學習,一起進步。

關於專案使用的技術棧

  • Vue:採用Vue的語法

  • Vuex:實現不同元件之間的狀態共享

  • vue-router:單頁應用路由管理必備

  • axios:發起http請求

  • SASS(SCSS):css預處理語言

專案

由於時間有限,只是做了個頁面的播放功能,其中用到了網易雲音樂的API網易雲,有興趣的可以去玩玩,其中也涉及到了一些知識點,在這與大家分享一下。

上圖

整個效果:

讓工作與(vue)音樂相伴
)

分享做這個單頁面的過程

這就是一個header元件,一個footer元件,一個musicList元件和一個paly元件組成的單頁面。

1. 如何獲取音樂的資料

我這是從網易雲音樂api扒出來的,扒出來之後新建一個檔案,把資料放進去,之後通過axios獲取,部分程式碼如下:

actions: {
    getData({ commit,state }) {
      if (localStorage.musics !== '[]' && localStorage.musics) {
        state.musicData = JSON.parse(localStorage.musics);
        return;
      }
      return new Promise((resolve, reject) => {
        Vue.axios.get('music-data')
            .then (res => {
              if (res.data.error === 0) {
                state.musicData = res.data.musicData;
                localStorage.musics = JSON.stringify(state.musicData);
              }
            })
            .then(() => {
              commit('toggleMusic',0)
            });
        resolve();
      });
    }
  }
複製程式碼

2. 刪除功能

我是在這刪除這個圖示下繫結了一個事件,主要就二句程式碼:

<span v-on:click="del(index)" class="del-icon"></span>
在methods定義del事件就好了
        del(index){
            this.$store.commit('del',index);
        }
複製程式碼

3. 尾部的播放控制

尾部的播放功能我一開始遇到了一個難題就是如何獲取歌曲的時間和控制播放的進度。後來通過查詢資料和百度解決了

獲取歌曲時間的部分程式碼如下:

 <span class="start">{{transformTime(now)}}</span>
 js部分程式碼
  this.nativeAudio = document.querySelector('audio');
    this.nativeAudio.addEventListener('play', () => {
      this.totalTime = this.transformTime(this.nativeAudio.duration);
      this.now = this.nativeAudio.currentTime;
      setInterval(() => {
        this.now = this.nativeAudio.currentTime;
      }, 1000)
    })
    
    transformTime(seconds) {
      let m, s;
      m = Math.floor(seconds / 60);
      m = m.toString().length == 1 ? ('0' + m) : m;
      s = Math.floor(seconds - 60 * m);
      s = s.toString().length == 1 ? ('0' + s) : s;
      return m + ':' + s;
    }
複製程式碼

控制播放進度的部分程式碼如下

changeTime(event) {
      let progressBar = this.$refs.progressBar;
      let coordStart = progressBar.getBoundingClientRect().left;  //getBoundingClientRect()方法返回元素的大小及其相對於視口的位置
      let coordEnd = event.pageX;
      this.nativeAudio.currentTime = (coordEnd - coordStart) / progressBar.offsetWidth * this.nativeAudio.duration;
      this.now = this.nativeAudio.currentTime;
      this.nativeAudio.play();
      this.$store.commit('play', true);
    },
touchMove(event) {
      let progressBar = this.$refs.progressBar;
      let coordStart = progressBar.getBoundingClientRect().left;
      let coordEnd = event.touches[0].pageX;
      this.$refs.now.style.width = ((coordEnd - coordStart) / progressBar.offsetWidth).toFixed(3) * 100 + '%';  //toFixed(3)保留小數點後3位
    },
touchEnd(event) {
      this.nativeAudio.currentTime = this.$refs.now.style.width.replace('%', '')/100 * this.nativeAudio.duration;
      this.now = this.nativeAudio.currentTime;
      this.nativeAudio.play();
      this.$store.commit('play', true);
    },
複製程式碼

4. 換膚

換膚主要提供了四種顏色,紅色 藍色 黑色 和綠色,樣式使用的是flex佈局,主要css程式碼如下:

.skin {
        position: absolute;
        display: flex;
        flex-direction: column;
        bottom: 50px;
        right: 15px;
        width: 30px;
        .skin-colors {
          flex: 4;
          width: 100%;
          display: flex;
          justify-content: center;
          align-items: center;
          flex-direction: column;
          .selected {
            border: 1px solid white;
          }
          i {
            flex: 1;
            display: inline-block;
            width: 20px;
            height: 20px;
            cursor: pointer;
            border-radius: 10px;
            margin-bottom: 5px;
          }
          i.one {
            background-color: #B72712;
          }
          i.two {
            background-color: #1565C0;
          }
          i.three {
            background-color: #212121;
          }
          i.four {
            background-color: #1B5E20;
          }
        }
        .icon-skin {
          flex: 1;
          width: 100%;
          height: 30px;
          background-repeat: no-repeat;
          background-size: contain;
          margin-top: 3px;
          cursor: pointer;
        }
        .icon-skin-red {
          background-image: url('./skinRed.svg');
        }
        .icon-skin-green {
          background-image: url('./skinGreen.svg');
        }
        .icon-skin-blue {
          background-image: url('./skinBlue.svg');
        }
        .icon-skin-black {
          background-image: url('./skinBlack.svg');
        }
複製程式碼

5. 控制歌曲的上一首下一首的播放

部分程式碼如下:

    prev() {
      this.audio.index = this.audio.index === 0 ? this.musicData.length - 1 : (--this.audio.index);
      this.$store.commit('toggleMusic', this.audio.index);
    }
    
    next() {
      this.audio.index = this.audio.index === this.musicData.length - 1 ? 0 : (++this.audio.index);
      this.$store.commit('toggleMusic', this.audio.index);
    }
複製程式碼

總結:通過模仿這個專案更加清楚地瞭解各元件之前的使用和不同元件的狀態共享。當然也遇到了一些坑,文章寫到這裡,也沒有完全寫完,只寫了一個單頁面,但也算是一個小小的總結,接下來附上我的原始碼:專案原始碼,有興趣的朋友可以看看順便幫忙點個star和fork,也希望能幫助到一些朋友。作為一名快要成為大四的學生,時間真的寶貴,對待學習也不敢懈怠,如果大家有什麼好的想法的話可以聯絡我的qq:137032979.碼字不容易,希望大家點個贊。前端路漫漫,與君共勉之。

讓工作與(vue)音樂相伴

相關文章