技術:React16
基於這個音樂播放器組件寫了一個簡單的webapp,功能更豐富!項目github地址
演示html
演示部分頁面react
以前基於Vue寫了一個播放器,帶各類功能,最後把本身繞死了。此次用React重寫了個,捨棄了那些沒用的功能,只保留了基本功能。而且利用媒體查詢適配移動端和手機端。之後會抽離成爲一個插件。git
點擊查看項目演示(可能由於會資源問題有歌曲播放不出來,若是發現我會及時解決的,目前是好的)github
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
事件API:webapp
全部的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爲播放進度條
讀取歌曲的緩衝進度,就要用到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開發播放器的失敗經驗,此次開發本着一個原則:精簡。並且在代碼的組織方式上也有了更多的思考,因此此次開發還比較順暢。喜歡的能夠給點個星星~