Skip to content

手写一个音频播放器 #139

@Dream4ever

Description

@Dream4ever

需求描述

iOS 和 Android 的 Webview 中自带的音频播放 UI 各不相同,为了在前端页面中呈现统一的效果,所以需要手写一个音频播放器,本质就是监听 audio 的各种事件,并按需调用它的各个方法。

关键代码

加载音频

在 HTML 中,通过 audio 标签来加载音频,同时想办法隐藏该元素。这样既可以展示自己的音乐播放器界面,也方便自己调用 audio 的各种接口,监听各种事件。

<audio id="audio" src=""></audio>

其属性、方法、事件请看 HTMLMediaElement - Web APIs | MDN

监听音频播放/暂停/结束事件

监听音频播放(包括继续播放)、暂停、结束这三个事件,前端 UI 需要根据各事件呈现对应的界面,让用户感知到当前的播放状态。

audio.addEventListener('play', function () {})
audio.addEventListener('pause', function () {})
audio.addEventListener('end', function () {})

监听音频当前播放时间点

音频在播放时,会触发 timeupdate 事件,在该事件中,访问 audio.currentTime 属性可以获取到音频当前所播放到的时间点。

然后前端 UI 就可以根据该属性实时更新音频播放进度,比如显示进度条、当前播放时刻等信息。

audio.addEventListener('timeupdate', function () {
  var currentTime = audio.currentTime
})

监听音频是否正在播放

return audio && audio.currentTime > 0 && !audio.paused && !audio.ended && audio.readyState > 2

参考 HTML5 check if audio is playing?

TODO: 完整浏览上面这个链接,完善该方法。

切换音频播放状态

根据上一条,可以获取到音频是否在播放中,如果正在播放,用户点击播放按钮就应该暂停播放 audio.pause(),如果处于暂停状态,用户点击播放按钮则应该恢复播放 audio.play()

前进/后退指定时长

一个常见的需求,就是将音频前进/后退 5s、10s、15s 等等,这个实现起来很简单:

var timeStep = 15
audio.currentTime += timeStep

拖拽改变播放进度

通过监听指定元素的 touchstarttouchmovetouchend 事件,可以获取到手指在拖拽起点、拖拽过程中、拖拽终点的坐标,然后再结合其它相关元素,便可用来改变音频的播放进度。

这里有一点要注意,就是在拖拽结束时,也就是在 touchend 事件中,再改变音频的 currentTime 属性。在拖拽过程中,也就是在 touchmove 事件里,只需实时更新显示在前端 UI 上的进度即可,音频还按拖拽前的进度正常播放就行。

seeker.addEventListener('touchstart', function(e) {
  var start = e.changedTouches[0].pageX
})
seeker.addEventListener('touchmove', function(e) {
  var diff = e.changedTouches[0].pageX
})
seeker.addEventListener('touchend', function(e) {
  var end = e.changedTouches[0].pageX
})

TODO

以上 JS 代码完善之后,可以封装成一个对象,对外暴露各种方法。再配合一套对应的 HTML + CSS,就是一个 MVP 版本的音频播放器了。

还可以参考 Building a Simple MP3 Audio Player in Vue.js 这篇文章进行重构。

forijk / vue-audio-better 的代码,也可以借鉴一下。

Audio - Vue.js Examples:这里有 Vue.js audio 的各种资源,可以参考。

Vue+ElementUI: 手把手教你做一个audio组件 也可以参考。

Metadata

Metadata

Assignees

No one assigned

    Labels

    Front-endEverything you see and experience

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions