技术: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开发播放器的失败经验,此次开发本着一个原则:精简。并且在代码的组织方式上也有了更多的思考,因此此次开发还比较顺畅。喜欢的能够给点个星星~