基於React的音樂播放器,適配PC端和移動端

基於React的適配PC端和移動端的輕量音樂播放器

技術:React16

更新

基於這個音樂播放器組件寫了一個簡單的webapp,功能更豐富!項目github地址

演示html

圖片描述

演示部分頁面react

圖片描述

寫在前面

以前基於Vue寫了一個播放器,帶各類功能,最後把本身繞死了。此次用React重寫了個,捨棄了那些沒用的功能,只保留了基本功能。而且利用媒體查詢適配移動端和手機端。之後會抽離成爲一個插件。git

點擊查看項目演示(可能由於會資源問題有歌曲播放不出來,若是發現我會及時解決的,目前是好的)github

點擊進入github查看代碼web

clipboard.png

圖片描述

功能

  • 播放,暫停
  • 上一曲,下一曲
  • 滑動或者點擊歌曲進度條實現音樂的快進快退
  • 音樂剩餘時間同步顯示
  • 緩衝進度條
  • 播放進度條
  • 音量控制
  • 點擊菜單按鈕展開與隱藏播放列表
  • 播放列表內音樂播放,刪除,當前播放音樂高亮顯示
  • 播放音樂時封面圖片旋轉,暫停時中止旋轉(只在PC端可查看,移動端隱藏音樂封面圖片)

說明

git clone git@github.com:neroneroffy/react-music-player.git

//安裝依賴
npm install

//啓動項目
npm start

//打包編譯
npm run build
API 說明 類型
info 傳入組件的歌曲數據 Array
onDel 刪除歌曲的回調函數 Function

info接收的參數類型爲一個對象數組npm

render() {
        const songInfo = [
            {
                src:"http://fs.w.kugou.com/201712281346/32b6de4127502b0f2defb32a859b7278/G048/M00/1B/0F/EJQEAFYl4ZuAUSEVAEIa293rBH4619.mp3",
                artist:"陶喆",
                name:"Melody",
                img:"http://imge.kugou.com/stdmusic/20150718/20150718174252663587.jpg",
                id:"66575568441"
            },
            {
                src:"http://fs.w.kugou.com/201712281315/2e497482c4283748d6b3d3e7912caada/G010/M07/1F/1D/qoYBAFUKLG2AFwOuAD6hYqqxfPE635.mp3",
                artist:"周杰倫",
                name:"千里以外",
                img:"http://imge.kugou.com/stdmusic/20170728/20170728122746411503.jpg",
                id:"43245456534"
            }
        ]
    return (
      <div className="App">
          <ReactMusicPlayer
            info={songInfo}
            onDel = {this.delSong}
          />
      </div>
    );
  }

onDel是當刪除播放列表內的歌曲時,觸發的函數數組

delSong(i,id){
        //接收兩個參數:i爲刪除的歌曲在播放列表中的位置;id爲刪除掉的歌曲的id
    }

開發

播放器底層是一個audio標籤,利用audio的API開發。用到的API有:app

  • audio.buffered; 返回已緩衝區域,TimeRanges
  • aduio.duration; 返回當前媒體的總時間
  • audio.currentTime; 當前播放的位置,賦值可改變位置
  • audio.paused; 是否暫停
  • audio.ended;是否結束
  • audio.play();播放
  • audio.pause();暫停
  • audio.volume;音量控制(0-1)

事件API:webapp

  • canplay; 是否能夠播放,但中途可能由於加載而暫停
  • timeupdate;播放時間更新

全部的API:http://blog.sina.com.cn/s/blo...函數

首先獲取audio對象,這裏我是用react的this.refs來獲取的

let audio = this.refs.audio;
<audio src={this.state.currentMusic.src?this.state.currentMusic.src:""} ref = "audio"></audio>

而後全局定義一個控制播放的函數,點播放調用一下,上一曲下一曲調用一下,一首歌結束後調用一下,播放列表切歌調用一下,播放列表刪除歌曲調用一下。哪裏須要哪裏調用,很方便。

圖片描述

接下來是寫進度條:
因爲移動端和PC端事件不同,因此分別綁定了不一樣的事件
buffered爲緩衝進度條,played爲播放進度條

clipboard.png

讀取歌曲的緩衝進度,就要用到audio.buffered這個屬性了,並且要在audio的timeupdate事件裏實時監聽,這裏把播放進度條的代碼也貼出來了。通過驗證:利用this.refs獲取DOM設置樣式,不會引發組件的更新渲染。性能可能要比在render裏函數監聽state的變化要好,相似下邊這種:

<div className="progress-buffered" ref="buffered" style={{width:"state裏計算好的長度%"}} ></div>

進度條實時變化的函數:

audio.addEventListener('timeupdate',()=>{
            //設置播放進度條
            let playPer = audio.currentTime/audio.duration;
            this.refs.played.style.width = playPer*100+"%";
            //設置緩衝進度條
            let timeRages = audio.buffered;
            let bufferedTime = 0
            if(timeRages.length !== 0){
                bufferedTime = timeRages.end(timeRages.length-1);
            }
            let bufferedPer = bufferedTime/audio.duration;
            this.refs.buffered.style.width = bufferedPer*100+"%";
            //設置剩餘時間
            let remainTime = parseInt(audio.duration - audio.currentTime);

            this.setState({
                remainTime:this.getTime(remainTime),
            });
            if(audio.ended){
                this.next()
            }
        })

拖動或點擊進度條,我分別對於PC端和移動端定義了一個事件,以後點擊或者拖動的時候分別調用就能夠啦:

//PC端
    setTimeOnPc(e){
        let audio = this.refs.audio;
        if(audio.currentTime !== 0) {
            let audio = this.refs.audio;
            let newWidth = (e.pageX - this.state.playedLeft) / this.refs.progress.offsetWidth;
            this.refs.played.style.width = newWidth * 100 + "%";
            audio.currentTime = newWidth * audio.duration;
        }
    }

    //移動端
    setTime(e){
        let audio = this.refs.audio;
        let newWidth = (e.touches[0].pageX-this.state.playedLeft)/this.refs.progress.offsetWidth;
        this.refs.played.style.width = newWidth*100 + "%";
        audio.currentTime = newWidth*audio.duration
    }

音量控制條的拖動和點擊也是同理,就不在複述一遍了。
播放列表的滑動動畫是用的ReactCssTransitionGroup實現的。
以上分享了最核心的功能,但願能夠有幸幫助到正在寫相似業務的童鞋。

總結

這個小組件源於本身想寫一個網站練練手,網站上會有播放音樂的功能,可是對現有的react音樂播放器插件不太滿意,因此索性本身開發了一個,連玩帶寫寫了兩天。由於有了上次用Vue開發播放器的失敗經驗,此次開發本着一個原則:精簡。並且在代碼的組織方式上也有了更多的思考,因此此次開發還比較順暢。喜歡的能夠給點個星星~

相關文章
相關標籤/搜索