基于React的适配PC端和移动端的轻量音乐播放器
基于React的适配PC端和移动端的轻量音乐播放器
技术:React16
之前基于Vue写了一个播放器,带各种功能,最后把自己绕死了。这次用React重写了个,舍弃了那些没用的功能,只保留了基本功能。并且利用媒体查询适配移动端和手机端。组件之间传值利用props,这个播放器先供自己用,以后会抽离成为一个插件。
点击查看项目演示
(可能因为会资源问题有歌曲播放不出来,如果发现我会及时解决的,目前是好的)
功能
- 播放,暂停
- 上一曲,下一曲
- 滑动或者点击歌曲进度条实现音乐的快进快退
- 音乐剩余时间同步显示
- 缓冲进度条
- 播放进度条
- 音量控制
- 点击菜单按钮展开与隐藏播放列表
- 播放列表内音乐播放,删除,当前播放音乐高亮显示
- 播放音乐时封面图片旋转,暂停时停止旋转(只在PC端可查看,移动端隐藏音乐封面图片)
说明
git clone aaa@qq.com.com:capslocktao/react-music-player.git
//安装依赖
npm install
//启动项目
npm start
//打包编译
npm run build
API | 说明 | 类型 |
---|---|---|
info | 传入组件的歌曲数据 | Array |
onDel | 删除歌曲的回调函数 | Function |
info接收的参数类型为一个对象数组
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有:
* audio.buffered; 返回已缓冲区域,TimeRanges
* aduio.duration; 返回当前媒体的总时间
* audio.currentTime; 当前播放的位置,赋值可改变位置
* audio.paused; 是否暂停
* audio.ended;是否结束
* audio.play();播放
* audio.pause();暂停
* audio.volume;音量控制(0-1)
事件API:
* canplay; 是否可以播放,但中途可能因为加载而暂停
* timeupdate;播放时间更新
所有的API:http://blog.sina.com.cn/s/blog_51e565eb01018tbp.html
首先获取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:"计算好的长度%"}} ></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
}
音量控制条的拖动和点击也是同理,就不在复述一遍了。
以上这些是最核心的功能,希望对大家有所帮助。
总结
这个小组件源于自己想写一个网站练练手,网站上会有播放音乐的功能,但是对现有的react音乐播放器插件不太满意,所以索性自己开发了一个,连玩带写写了两天。因为有了上次用Vue开发播放器的惨痛教训,这次开发本着一个原则:精简。而且在代码的组织方式上也有了更多的思考,所以这次开发还比较顺畅。喜欢的可以给点个星星~
上一篇: Flutter 列表踩坑
下一篇: Flutter 开发踩坑记录(干货总结)