原文地址: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音乐播放器的更多相关文章

  1. 一个简单的ipfs音乐播放器的实现

    IPFS音乐播放器 IPFS相关 IPFS第一次亲密接触 什么是IPFS IPFS对比HTTP/FTP等协议的优势 IPFS应用场景 -移动数据 交易 路由 网络 定义数据 命名 使用数据 具体场景; ...

  2. 一个简单的Android音乐播放器

    Android小白的期末作业 Android期末项目,仅用作学习使用,在线音乐部分只获取了网易云热歌榜,API来自鼻子亲了脸 传送门: GitHub 参考: anddiencn 实现功能 展示出本地的 ...

  3. 一个功能齐全的IOS音乐播放器应用源码

    该源码是在ios教程网拿过来的,一个不错的IOS音乐播放器应用源码,这个是我当时进公司时 我用了一晚上写的  图片都是在别的地方扒的,主要是歌词同步,及上一曲,下一曲,功能齐全了 ,大家可以学习一下吧 ...

  4. 用<audio>标签打造一个属于自己的HTML5音乐播放器

    上一章节,我们刚刚讲了<video>标签,今晚,我们讲的是<audio>标签,这两个东东除了表示的内容不一样以外,其他的特性相似的地方真的太多了,属性和用法几乎一样,也就说,如 ...

  5. 一个基于H5audio标签的vue音乐播放器

    <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8&quo ...

  6. 4个小时实现一个HTML5音乐播放器

    技术点:ES6+Webpack+HTML5 Audio+Sass 这里,我们将一步步的学到如何从零去实现一个H5音乐播放器. 首先来看一下最终的实现效果:Demo链接 接下来就步入正题: 要做一个音乐 ...

  7. Swift - 制作一个在线流媒体音乐播放器(使用StreamingKit库)

    在之前的文章中,我介绍了如何使用 AVPlayer 制作一个简单的音乐播放器(点击查看1.点击查看2).虽然这个播放器也可以播放网络音频,但其实际上是将音频文件下载到本地后再播放的. 本文演示如何使用 ...

  8. 如何用vue打造一个移动端音乐播放器

    写在前面 没错,这就是慕课网上的那个vue音乐播放器,后台是某音乐播放器的线上接口扒取,虽然这类项目写的人很多,但不得不说这还是个少有的适合vue提升的好项目,做这个项目除了想写一个比较大并且功能复杂 ...

  9. 记一次酷狗音乐API的获取,感兴趣的可以自己封装开发自己的音乐播放器

    1.本教程仅供个人学习用,禁止用于任何的商业和非法用途,如涉及版权问题请联系笔者删除. 2.随笔系作者原创文档,转载请注明文档来源:http://www.cnblogs.com/apresunday/ ...

随机推荐

  1. C#面向对象通信

    面向对象通信编程: 看起来像是调用本地的函数,就得到了结果: 实际上参数是传递到了远程机器上了,而函数也是在远程机器上运行的.

  2. 用mapreduce实现将mysql数据导出到HDFS上

    因为业务需要,需要将一批mysql数据导入到HBASE,现在先将数据从Mysql导出到HDFS. 版本:hadoop CDH4.5,Hbase-0.946 1.实体类 YqBean 是我的实体类,请根 ...

  3. Java常用文件下载与查找的URL

    Java JDK: http://www.oracle.com/technetwork/java/javase/downloads/index.html Tomcat: http://tomcat.a ...

  4. arm-linux-copydump 的使用

    生成可以执行的 2 进制代码 [arm@localhost gcc]#arm­linux­copydump ­O binary hello hello.bin

  5. 解决VS2012新建MVC4等项目时,收到此模板加载程序集“NuGet.VisualStudio.Interop…”的错误

    1.错误如图所示: 2.不管是VS2012,还是2013如果开始没安装Nuget包都或报这个错,因为VS2012就已经全面切换到使用NuGet这个第三方开源工具来管理项目包和引用模块了,使用VS201 ...

  6. Java获取文件Content-Type(Mime-Type)

    Java获取文件Content-Type(Mime-Type) 刚好工作中要用到,所以总结一下.推荐使用第一种和第三种,实在不行,也可以去把http://tool.oschina.net/common ...

  7. [java]反转单项链表,用O(n)时间和O(1)空间

    链表数据结构 public class ListNode { public int val; public ListNode next; public ListNode(int x) { val = ...

  8. yii2使用vendor文件夹下的的css文件

    yii2 使用 vendor 下在css样式, 可以新建一个Asset,定义 public $sourcePath="@vendor/..",如:public $sourcePat ...

  9. Win10下使用默认的照片查看器

    在打开图片的时候默认是 画图,我们想要用windows图片器打开,但是更多应用里面没有这一选项, 按 Windows徽标键+R键,打开运行命令窗口,输入"regedit"命令 来打 ...

  10. Remember, every day is a miracle.

    Remember, every day is a miracle.请记住,每一天都是一个奇迹.