实现思路
-
原生的audio标签,controls属性用于控制是否显示一个默认的播放器,这个播放器的样式是浏览器决定的,如果使用默认播放器,在不同的浏览器中呈现的样式会不一样。要实现自定义播放器样式,就不要去设置control(因为controls默认值为false)。
-
通过监听原生audio标签的事件,以及调用原生audio标签的方法,来实现对音频的控制。自定义播放器只是一个躯壳,本质的操作全在audio标签上。
-
因为该vue项目使用了vant,中间的滑条就直接使用了vant的slider组件。当然,也可以使用vue-slider-component组件,或者自己手写一个小轮子。
-
用动作去更新状态。而不是先更新状态,再监听状态变更去执行动作。因为动作执行不一定会成功,如果状态跟执行结果不一样就很尴尬了。
效果预览
(看起来非常简单,或者说简陋,因为平时对audio并没有什么接触,此文仅作笔记之用。)
audio的常用的属性
controls
。如果声明了该属性,浏览器将提供一个包含声音,播放进度,播放暂停的控制面板,样式由浏览器决定。currentTime
。当前音频已播放时长。duration
。当前音频总时长。preload
。预加载,这是一个枚举属性,none
表示不做预加载,metadata
表示会对元数据(比如音频时长)做预加载,auto
表示会尝试对元数据以及音频柳做完全预加载。src
。音频文件的地址。playbackRate
。播放速度。网上常见的1x
,1.5x
,0.5x
播放速度就是利用该属性实现的。
audio的常用的事件
loadedmetadata
。表示音频元数据已经被加载,我们一般在这里通过event.target.duration
获取音频总时长。canplay
。这个事件会在loadedmetadata
之后触发,表示音频可以被播放了。canplaythrough
。这个事件会在canplay
之后触发,表示浏览器认为不出意外的话音频可以被播到最后。play
。表示音频已开始播放。pause
。表示音频已暂停播放。ended
。表示播放完了最后一帧。error
。表示播放出错,可能是音频文件地址无效,或者音频格式不支持。timeupdate
。表示正在播放中,播放过程中会被频繁触发,一般在这里通过event.target.currentTime
来实时获取已播放时长。
audio的常用的方法
play
。播放音频。此方法会返回一个Promise
对象。不需要音频数据已经加载到能够播放的状态。如果录音文件地址可用,会走到fulfilled
状态;如果录音文件地址不可用或者缺失,会走到rejected
状态;pause
。暂停音频。返回值和行为均与play
一样。
常用场景实现
1,显示音频时长如何实现?
答:监听loadedmetadata
,通过event.target.duration
取出音频总时长,因为音频总时长单位为秒,所以一般情况下都会有一个秒转换为时分秒格式的需求,而且一般情况下还要补0,实现如下:
const filterDuration = (s=0) => {
if (typeof s !== 'number') {
throw new Error('传入时长需为数字类型')
};
let hour = Math.floor(s / 3600);
let min = Math.floor((s % 3600) / 60);
let sec = Math.floor(s % 60);
hour = hour < 10 ? `0${hour}` : hour;
min = min < 10 ? `0${min}` : min;
sec = sec < 10 ? `0${sec}` : sec;
return `${hour}:${min}:${sec}`;
}
2,如何动态获取当前播放百分比?
答:监听timeupdate
事件,通过event.target.currentTime / event.target.duration
来计算百分比。这里我遇到了一个比较奇特的问题:当音频时长很短时(比如只有几秒钟),有时候event.target.currentTime
会大于音频总时长。所以我针对播放进度百分比大于100%的情况做了处理,目前不是太明白该现象原因所在。
写在最后
这只是对audio标签的一个入门使用,实际上我对audio了解得并不多,特此记录一些基础操作,方便后续自己翻阅。