当前位置: 首页 > Web前端 > HTML5

用TS+Vue重写APlayerHTML5音乐播放器

时间:2023-04-05 10:59:10 HTML5

简介@DIYgod/APlayer是一款简洁美观的HTML5音乐播放器(〃?ω?)当我第一次看到这款播放器的颜值时,让我眼前一亮。真的很佩服那些能设计出漂亮界面的设计师(*>ω<)但是用了之后发现还是有不足的地方。这是我提到的问题。我用了一段时间,喜欢APlayer简单的UI。我想提出一些其他改进建议:1.我认为有必要提供一个动态管理播放列表的API(如果没有,则只能在需要动态添加歌曲到列表时重新初始化)2.一个应提供销毁播放器的API3.歌词允许异步添加,获取歌词的接口通常是Separate(必须等待歌词接口返回后再初始化播放器,如果获取歌词失败或时间过长,同时会影响音乐播放功能)关于第三项,APlayer其实支持异步歌词但只支持导入.lrc文件如果像网易云/QQ音乐一样返回JSON格式的地址,那么就不满足要求。为什么不提PR,重写?想了想,最后还是觉得还是组件化的方式开发比较好(原来APlayer用的是原生JS,不依赖其他库),因为我还在工作的时候自己写了一个音乐播放器后台(仿微博播放器,那个时候不知道怎么用Git源码已经丢了)所以很有经验,重写一个难度不大,比较随意,大家也可以随便加点东西qwq截图说明:这个播放器是基于@DIYgod/APlayer的布局和样式使用TS+Vue组件重构的演示:http://aplayer.quq.cat文档:http://aplayer.quq.cat/docs源码:https://github.com/MoeFE/vue-...npm:https://www.npmjs.com/package...播放列表来自网易云播放列表:http://music.163.com/#/playli...喜欢的话别忘了点个star(*ゝω?)欢迎提Issues和PR(′?_?`)Frameworkselection为了大家方便,我选择的是Vue,它可以响应式的控制播放器的各种属性,并以插件的形式发布使用(详见demo)。为了方便更好的调试,我在生产环境中开启了SourceMap和devtools。如果你已经安装了vue-devtools可以打开调试器查看组件划分和各个组件的信息。至于为什么选择使用TypeScript,本文不会过多解释。您可以在Internet上找到TypeScript和JavaScript之间的区别。我只能告诉你:对于一个用过C#的开发者来说,这简直不要太爽。微软之父赛高(*>ω<)最后推荐一个TS+Vue脚手架模板:https://github.com/Toilal/vue...以后可能会添加到官方模板:https://github。com/vuejs-temp...TS+React脚手架可以使用这个:https://github.com/wmonk/crea...拆分组件并获取布局样式后首先要做的就是拆分组件和复制@DIYgod/APlayer的布局和样式确保样式没有问题,然后分别复制每个组件的布局和样式。如果您不了解设计,则必须复制它。请允许我做一个悲伤的表情(???)我将播放器分为以下几个组件:.ts歌曲信息组件Lyric.ts歌词面板组件Progress.ts进度条组件Time.ts播放时间组件Volume.ts音量控制组件List.ts播放列表组件Item.ts播放列表项组件这里有更清晰的图:点击查看高-definitionoriginalimage功能开发功能开发其实没有那么难。HTML5已经封装了HTMLAudioElement元素。我们只是使用它的API和视图来进行数据绑定和交互。看看文档就好了,不过这里会有一个小问题。问题是Vue无法监听Audio对象的属性变化,因为Audio对象其实就是HTMLAudioElement元素,而Vue无法监听元素属性变化,所以想了个小办法,定义一个Media接口,这个接口定义和Audio对象一样属性,同步Audio事件中的Media属性。这样,您就可以使用Media对象以响应方式获取Audio属性值。可以查看这段代码:APlayer.ts#L326-L334这里简单介绍一些常用的属性和方法。name表示autoplay是否自动播放(Safari中无效,可以在初始化音频后手动调用play方法)buffered获取缓冲进度(必须在readeyState>=3之后获取,否则会抛出异常)loop是否循环播放音频(建议根据当前播放模式实现此功能)preload预加载选项,建议使用元数据,只在不播放时获取音频长度,而不是loadingtheentireaudiosrctogetorsettheplaybackaddressoftheaudiovolume获取或设置音频的音量(0~1)paused获取当前音频是否暂停currentTime获取或设置当前音频的播放进度(单位:second)duration获取当前音频的时长(单位:秒)playbackRate获取或设置当前音频的播放速度play()playaudiopause()pauseaudio点击查看所有Media事件其实就是Audio和Video对象几乎属于Media,所以如果你能开发音乐播放器,你也会开发视频播放器这里我们重点关注timeupdate事件。该事件在音频播放过程中不断触发。这可以说是最有用的事件了,因为播放过程中需要不断重绘播放器的播放进度和播放时间。如果有歌词,还可以根据当前播放时间同步歌词。如果您没有或不知道此事件,您可以使用setInterval而不是使用setInterval。会有两个问题:1.什么时候重绘合适?太快影响性能,太慢页面不同步2.如果用户暂停播放,需要清空定时器,播放开始时需要初始化定时器。一个空定时器)LRC歌词解析和同步可能是做这个功能时最好玩的qwq因为我对这个功能很敏感所以很久以前千千静听无聊的时候就试着做了最好的(′?_?`)这里的主要功能是歌词分析。如果同步了歌词,只需计算出与当前播放时间最匹配的item元素,然后将歌词面板的滚动条位置设置为当前元素的位置即可。常见的时间戳有以下几种:[mm:ss]只有分秒时间戳[mm:ss:ms]分、秒、毫秒时间戳[mm:ss.ms]有分、秒、毫秒时间标签的另一种格式[mm:ss:ms][mm:ss.ms]多个时间标签共享同一个歌词我的想法是:先把歌词文本按照行划分成一个数组,然后逐行解析,使用正则表达式匹配该行的分秒毫秒和显示的歌词文本,将分秒毫秒转换为毫秒,相加后与歌词文本关联,保存在一个数组中,最后需要按照时间的正序排列,那么当前要显示的歌词=过滤数组中的时间<当前播放时间之后的最后一项privateasyncparseLRC():Promise{if(!this.lrc||this.lrc==='loading')returnif(this.isURL(this.lrc)){//如果歌词是URL地址,请求该地址获取歌词文本const{data}=awaitAxios.get(this.lrc.toString())this.currentLRC=data}elsethis.currentLRC=this.lrcconstreg=/\[(\d+):(\d+)[.|:](\d+)\](.+)/constregTime=/\[(\d+):(\d+)[.|:](\d+)\]/gconstregCompatible=/\[(\d+):(\d+)]()(.+)/constregTimeCompatible=/\[(\d+):(\d+)]/gconstregOffset=/\[offset:\s*(-{0,1}\d+)\]/constoffsetMatch=this.lrc.match(regOffset)constoffset=offsetMatch?Number.parseInt(offsetMatch[1]):0this.LRC=[]constmatchAll=(line:string)=>{letmatch=line.match(reg)||line.match(regCompatible)如果(!match)返回如果(match.length!==5)returnconstminutes=Number.parseInt(match[1])||0constseconds=Number.parseInt(匹配[2])||0const毫秒=Number.parseInt(match[3])||0consttime=(minutes*60*1000+seconds*1000+milliseconds)+offsetconsttext=(match[4]asstring).replace(regTime,'').replace(regTimeCompatible,'')如果(!text)return//优化:不显示空行this.LRC.push({time,text})matchAll(match[4])//递归匹配多个时间标签}this.currentLRC.replace(/\\n/g,'\n').split('\n').forEach(line=>matchAll(line))//歌词格式不支持if(this.LRC.length<=0)this.LRC=[{time:-1,text:'(·?·*)抱歉,不支持此歌词格式'}]elsethis.LRC.sort((a,b)=>a.time-b.time)}点击查看完整的代码总结,改进原APlayer的不足:1.播放器属性可以响应式自由控制2.歌词同步支持多种时间标签格式(fix#39)3.歌词同步兼容[offset:0]标签4.支持异步歌词5.允许控制播放速度(同一首歌听不同速度quq会有不同的感觉)6.音量允许拖动控制7.支持注册所有媒体事件8.保存播放器配置到localStorage刷新后可以恢复播放进度等信息,体验用TS写Vue的快感w最后弱:@MoeFE欢迎大家加入(??????)??呃……没要求,头像一定要萌萌哒!!好想要一个能带我装坚强带我飞的大佬(??_?)?