Audio 标签的使用和自己封装一个强大的React音乐播放器
原文地址:https://www.dodoblog.cn/blog?id=5be84d5c70b2b617f27a4610
这篇文章主要介绍一下博客里的这个音乐播放器是怎么写的
为了更好的表达高深的东西,还是需要先强调点简单的东西
Audio元素的属性
paused 是否暂停,不可以修改
audio.paused = true // 错误
audio.pause() // 正确
currentTime 当前播放的时间,也可以用来改变进度,以下两行代码是等价的
audio.currentTime =
audio.play()
duration 获取当前加载好的音乐的时间
loop 是否单曲循魂
mute 是否静音
volume 音量大小,数值是0 到 1
Audio元素的事件
play和pause
播放和暂停的时候触发的事件
seeking和seeked
这里的快进是时间突然到某一个点上,不是倍速播放,快进开始和快进完成分别触发一个不同事件,因为快进了可能需要加载数据,需要一点点时间
比如改变currentTime
loadstart,loadeddata和canplay
开始加,加载了一帧数据,加载到足够播放的数据
ended
结束的时候,结束了播放下一首用
还有一些事件,比如progress, volumnchange 这些方法,随便搜一下就可以知道了,大家需要自行搜去,正常情况下这些就够用了。
React播放器
参数
<MusicPlayer
getAudio={audio => this.audio = audio}
musics={store.musicStore.currentList.songs}
/>
为了方便启用,核心的参数只有两个
getAudio,和ref一样,可以返回当前的audio元素 musics是一个音乐的列表
因为在audio元素的基础上开发,所以几乎所有的事件其实也都是在audio上通过监听获取到,所以把audio元素抛出可以减少很多配置
传入一个数组 这个数组是一个音乐列表的信息
每个对象应该包括 id,封面图链接,歌曲链接,歌词链接,歌唱家,歌曲名称
样式
我写的这个播放器是这样的,很简单的样子,基本功能都有,没有循环播放和随机播放的设置,其实也很简单


这个播放器的主要元素包括
封面,歌曲列表,名称,歌词,进度,上一首下一首,还有封面上那个钱币一样的按钮是播放暂停
然后侧面的两个按钮可以控制播放器的显示隐藏和歌曲列表的显示隐藏
具体的UI大家想象着写就好了,反正我写的也不算好看
留出那几个控制的按钮绑定事件就好了
初始化
componentDidMount() {
const musics = this.props.musics
const audio = this.$audio.current
this.setState({
currentIndex: musics && musics.findIndex(item => item.id === window.localStorage.getItem('current-music-id')) || ,
})
audio.addEventListener('play', this.handlePlay)
audio.addEventListener('pause', this.handlePause)
this.props.getAudio && this.props.getAudio(audio)
}
初始化的时候,
1. 添加了事件监听,这样当外部改变audio的状态也会改变播放器组件的状态
2. 获取localstorage里的音乐,这个很友好,可以刷新仍然是那一首歌
3. 抛出audio元素
播放和暂停
handlePlay = () => {
const music = this.props.musics[this.state.currentIndex]
const audio = this.$audio.current
this.handleLoadLrc()
this.setState({ paused: false })
window.localStorage.setItem('current-music-id', music.id)
audio.play(audio.currentTime)
this.timer = setInterval(() => {
const { currentTime, duration } = audio
this.setState({ currentTime, duration })
}, )
}
handlePause = () => {
this.setState({ paused: true })
this.$audio.current.pause()
this.timer && clearInterval(this.timer)
}
注意
1. currentIndex表示当前的播放的音乐的index
2. 我们设置了pause的属性 是记录播放器的当前状态,audio的状态改变不能实时反应去渲染dom,所以需要用自己的state记录。
3. play需要传入当前的audio时间,这样暂停播放不会重新开始,而切换后currentTime也会归0
4. 动态记录了currentTime和duration,并且用计时器不对获取,也是因为我们并没有办法实时获取时间反映到进度条上
上一首,下一首和切换
handleNext = () => {
let currentIndex = this.state.currentIndex +
if (currentIndex >= this.props.musics.length) {
currentIndex =
}
this.setState({currentIndex }, this.handlePlay)
}
handlePrev = () => {
let currentIndex = this.state.currentIndex -
if (currentIndex < ) {
currentIndex = this.props.musics.length -
}
this.setState({currentIndex }, this.handlePlay)
}
handleToggle = currentIndex => {
this.setState({currentIndex }, this.handlePlay)
}
上一首就是index - 1然后播放,如果index = 0 那么index为最后一个
下一首就是index +1然后播放,如果index已经最大 那么index重置0
切换就是接受一个index 改变后播放
这三个超级简单,不多解释
快进
handlePlayFrom = e => {
const audio = this.$audio.current
const { left, width } = e.target.getBoundingClientRect()
const clickPos = (e.clientX - left) / width
const time = audio.duration * clickPos
if (!time) return false
audio.currentTime = time
}
这个稍微考验些关于dom位置判断的功底
通过获取进度条的宽度,点击的位置,然后计算出一个进度的百分比,最后根据这个百分比和总的音乐时长计算出点击点的时间
加载歌词
handleLoadLrc = () => {
const request = new XMLHttpRequest();
const url = this.props.musics[this.state.currentIndex].lrc
request.open('GET', url, true);
request.onload = () => {
this.lyricStr = request.response
}
request.send();
}
播放的时候回去加载歌词,就是一个ajax请求,返回的歌词一般都是这样的格式

看起来像个数组,其实是一个字符串,然后我们可以通过正则将其拆分成一个时间 歌词一一对应的数组,这个是最麻烦的一点,但其实并没有什么技术复杂度,主要就是处理字符串通过split拆分成数组就好
然后根据当前的currentTime获取需要显示的那句歌词
不细节分析了,有需要的可以在我的github上看
切换歌单
componentDidUpdate(nextProps) {
if (nextProps.musics !== this.props.musics) {
this.setState({ currentIndex: }, this.handlePlay)
}
}
当音乐列表发生改变的时候,重新播放就好了
播放器的显示隐藏
动态添加一个class去隐藏整个播放器就好啦,fixed定位,很容易搞定的
播放器的基本功能就这么多啦,当然还有一些,比如设置播放模式,依次还是随机,是否单曲循环等等,这些其实都很简单。
具体的代码
戳这里 获取播放器的代码,有需要的自取
总结,在audio元素的基础上开发是比较简单的,但是这也有很多不好的地方,比如说,别人找到audio元素,然后加一个controls属性,就可以下载音乐了。
真正强大的是Audio API,W3C提供了操作音频的一系列api 可以实现更好的音频buffer 播放效果,甚至通过analyser分析音频进行mix混音以及音乐效果的改变。
还可以写好玩的动画效果,比如

这些的前提当然是需要对音乐有一定的了解,有兴趣的小伙伴可以研究一下哦,这是很有趣的一个方向。
Audio 标签的使用和自己封装一个强大的React音乐播放器的更多相关文章
- 一个简单的ipfs音乐播放器的实现
IPFS音乐播放器 IPFS相关 IPFS第一次亲密接触 什么是IPFS IPFS对比HTTP/FTP等协议的优势 IPFS应用场景 -移动数据 交易 路由 网络 定义数据 命名 使用数据 具体场景; ...
- 一个简单的Android音乐播放器
Android小白的期末作业 Android期末项目,仅用作学习使用,在线音乐部分只获取了网易云热歌榜,API来自鼻子亲了脸 传送门: GitHub 参考: anddiencn 实现功能 展示出本地的 ...
- 一个功能齐全的IOS音乐播放器应用源码
该源码是在ios教程网拿过来的,一个不错的IOS音乐播放器应用源码,这个是我当时进公司时 我用了一晚上写的 图片都是在别的地方扒的,主要是歌词同步,及上一曲,下一曲,功能齐全了 ,大家可以学习一下吧 ...
- 用<audio>标签打造一个属于自己的HTML5音乐播放器
上一章节,我们刚刚讲了<video>标签,今晚,我们讲的是<audio>标签,这两个东东除了表示的内容不一样以外,其他的特性相似的地方真的太多了,属性和用法几乎一样,也就说,如 ...
- 一个基于H5audio标签的vue音乐播放器
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8&quo ...
- 4个小时实现一个HTML5音乐播放器
技术点:ES6+Webpack+HTML5 Audio+Sass 这里,我们将一步步的学到如何从零去实现一个H5音乐播放器. 首先来看一下最终的实现效果:Demo链接 接下来就步入正题: 要做一个音乐 ...
- Swift - 制作一个在线流媒体音乐播放器(使用StreamingKit库)
在之前的文章中,我介绍了如何使用 AVPlayer 制作一个简单的音乐播放器(点击查看1.点击查看2).虽然这个播放器也可以播放网络音频,但其实际上是将音频文件下载到本地后再播放的. 本文演示如何使用 ...
- 如何用vue打造一个移动端音乐播放器
写在前面 没错,这就是慕课网上的那个vue音乐播放器,后台是某音乐播放器的线上接口扒取,虽然这类项目写的人很多,但不得不说这还是个少有的适合vue提升的好项目,做这个项目除了想写一个比较大并且功能复杂 ...
- 记一次酷狗音乐API的获取,感兴趣的可以自己封装开发自己的音乐播放器
1.本教程仅供个人学习用,禁止用于任何的商业和非法用途,如涉及版权问题请联系笔者删除. 2.随笔系作者原创文档,转载请注明文档来源:http://www.cnblogs.com/apresunday/ ...
随机推荐
- solr 如何实现精确查询
第一条和第三条不应该出现的. 解决办法
- SpringAOP中的注解配置
使用注解实现SpringAOP的功能: 例子: //表示这是被注入Spring容器中的 @Component //表示这是个切面类 @Aspect public class AnnotationHan ...
- Number Sequence /// oj21456
题目大意: 有一组规律数 the first 80 digits of the sequence are as follows: 1 12 123 1234 12345 123456 1234567 ...
- USACO2007 Protecting the Flowers /// 比值 前缀和 oj21161
题目大意: 有N (2 ≤ N ≤ 100,000) 头牛偷吃花 将牛赶回牛棚需Ti minutes (1 ≤ Ti ≤ 2,000,000) 每头牛每分钟能吃Di (1 ≤ Di ≤ 100) 朵花 ...
- Producer-Consumer 生产者,消费者
这个模式跟Guarded模式有点类似,不过需要一个控制台限制请求方和处理方的频度和数量. public class ProducerConsumerTest { /** * @param args * ...
- mysql 数据库基本命令
停止mysql服务:net stop mysql //管理员方式运行 启动mysql服务:net start mysql 进入数据库:mysql -u root -p 查看数据库:show ...
- sslforfree的证书合并成类似于certbot的ssl证书文件
之前的證書都是通過 certbot的命令生成的,但是目前一個服務器太多個網站,太多個ssl證書,證書過期之後,目前是 通過 ssl for free 網站再生成新的 ssl證書,再次更新證書週期 Le ...
- ci 连接myssql
由于要将mssql 和 mysql 里面的数据进行对比,So. 配置:database.php $db['default']['hostname'] = '192.168.1.222'; $db['d ...
- maven创建archetyp一直显示runing
在maven的五分钟入门里面,有这样一个命令: mvn archetype:generate -DgroupId=com.mycompany.app -DartifactId=my-app -Darc ...
- iptables 命令大全
1.连续端口配置 iptables可以方便的配置多个端口.其中根据端口的连续性,又可分为连续端口配置和不连续端口配置. 如: -A INPUT -p tcp –dport 21:25 -j DROP/ ...