一、播放器的主要功能
1、播放/暂停
2、音量控制
3、播放速度控制
4、播放进度条
5、下载
播放器如下:

二、代码实现
自定义播放器是基于html5的一个<audio>标签完成的,逻辑处理使用vue完成的。
html代码:
<Row class="audio-player" type="flex" align="middle" justify="start" :disabled="!audioFile">
<!-- 速度控制 -->
<Icon
class="control-icon"
type="ios-rewind"
size="20"
color="#5e72e4"
@click="changeSpeedSlow"
/>
<Icon
v-show="showPlay"
class="control-icon"
type="ios-pause"
size="20"
color="#5e72e4"
@click="handlePlay"
/>
<Icon
v-show="!showPlay"
class="control-icon"
type="ios-play"
size="20"
color="#5e72e4"
@click="handlePlay"
/>
<Icon
class="control-icon"
type="ios-fastforward"
size="20"
color="#5e72e4"
@click="changeSpeedFast"
/>
<span class="speed-span">X{{ multipleArray[multipleIndex] }}</span>
<audio
id="audioPlayer"
ref="audio"
preload="metadata"
:src="audioFile"
controlslist="nodownload"
@loadedmetadata="onLoadedmetadata"
@timeupdate="onTimeupdate"
@volumechange="onVolumechange"
@ended="onAudioEnded"
>
{{ $t("unsupportedTip") }}
</audio>
<!-- 播放进度条 -->
<Row
class="audio-controls"
type="flex"
align="middle"
justify="space-between"
>
<span id="currentTime">{{ currentTime }}</span>
<input
class="progress-bar"
ref="progressbar"
type="range"
:value="sliderTime"
step="any"
min="0"
max="100"
@input="handleProgress($event)"
/>
<span id="duration">{{ duration }}</span>
</Row>
<!-- 音量操作 -->
<Tooltip class="audio-mute" placement="left" theme="light">
<Icon
v-show="!isMute"
class="control-icon"
type="md-volume-up"
size="20"
color="#dbdbdb"
@click.stop="handleMute"
/>
<Icon
v-show="isMute"
class="control-icon"
type="md-volume-off"
size="20"
color="#dbdbdb"
@click.stop="handleMute"
/>
<input
slot="content"
class="mute-bar"
ref="mutebar"
type="range"
:value="volume"
step="any"
min="0"
max="100"
@input="hancleChangeVolume($event)"
/>
</Tooltip>
<!-- 下载操作 -->
<Tooltip class="audio-download" placement="top" theme="light">
<Icon class="control-icon" type="md-more" size="20" color="#c4c5c6" />
<Icon
slot="content"
size="20"
type="md-download"
@click="handleDownload"
/>
</Tooltip>
</Row>
css代码:
.audio-player {
.control-icon {
margin-right: 5px;
}
.control-icon:hover {
cursor: pointer;
}
.speed-span {
display: inline-block;
width: 30px;
margin-right: 10px;
color: #747474;
}
.audio-controls {
display: flex;
align-items: center;
justify-content: space-between;
width: 170px;
margin-right: 5px;
.progress-bar {
width: 54%;
height: 4px;
cursor: pointer;
}
// 去除进度条边框
input[type="range"]:focus {
outline: none;
}
input[type=range]{
-webkit-appearance: none;/*清除系统默认样式*/
outline: none;
background: -webkit-linear-gradient(#5e72e4, #5e72e4) no-repeat, #eeeeee; /*背景颜色,俩个颜色分别对应上下,自己尝试下就知道了嗯*/
background-size: 0% 100%;/*设置左右宽度比例*/
height: 4px; /*横条的高度,细的真的比较好看嗯*/
border-radius: 1px;
}
/*拖动块的样式*/
input[type=range]::-webkit-slider-thumb {
-webkit-appearance: none;/*清除系统默认样式*/
width: 10px;
height: 10px;
background: #5e72e4;/*拖动块背景*/
border-radius: 50%; /*外观设置为圆形*/
}
input[type=range]::-webkit-slider-thumb:hover {
-webkit-appearance: none;
border: 6px solid #5e72e4; /*设置边框*/
}
input[type=range]::-moz-range-thumb {
width: 8px;
height: 8px;
background: #5e72e4;/*拖动块背景*/
border-radius: 50%; /*外观设置为圆形*/
color: transparent; //去除内阴影
border-color: transparent; //去除原有边框
}
input[type=range]::-moz-range-thumb:hover {
-webkit-appearance: none;
border: 2px solid #5e72e4; /*设置边框*/
}
}
.audio-mute {
.ivu-tooltip-inner {
width: 80px;
display: flex;
align-items: center;
}
.mute-bar {
width: 100%;
background-color: #e5e7e8;
height: 4px;
cursor: pointer;
}
// 去除进度条边框
input[type="range"]:focus {
outline: none;
}
input[type=range]{
-webkit-appearance: none;/*清除系统默认样式*/
outline: none;
background: linear-gradient(#545555, #545555) no-repeat, #eeeeee; /*背景颜色,俩个颜色分别对应上下,自己尝试下就知道了嗯*/
background-size: 0% 100%;/*设置左右宽度比例*/
height: 4px; /*横条的高度,细的真的比较好看嗯*/
border-radius: 1px;
}
/*拖动块的样式*/
input[type=range]::-webkit-slider-thumb {
-webkit-appearance: none;/*清除系统默认样式*/
width: 10px;
height: 10px;
background: #545555;/*拖动块背景*/
border-radius: 50%; /*外观设置为圆形*/
}
input[type=range]::-webkit-slider-thumb:hover {
-webkit-appearance: none;
border: 6px solid #545555; /*设置边框*/
}
input[type=range]::-moz-range-thumb {
-webkit-appearance: none;/*清除系统默认样式*/
width: 8px;
height: 8px;
background: #545555;/*拖动块背景*/
border-radius: 50%; /*外观设置为圆形*/
color: transparent; //去除内阴影
border-color: transparent; //去除原有边框
}
input[type=range]::-moz-range-thumb:hover {
-webkit-appearance: none;
border: 2px solid #545555; /*设置边框*/
}
}
.audio-download {
.ivu-tooltip-arrow {
display: none;
}
.ivu-icon-md-download:hover {
cursor: pointer;
}
}
}
js代码:
export default {
name: "audio-play",
props: {
audioFile: String,
},
data() {
return {
audioAllDuration: 0, //音频总播放秒数
multipleArray: [0.5, 0.75, 1, 1.25, 1.5, 2, 3],
multipleIndex: 2,
timer: "",
showPlay: false,
currentTime: "00:00",
duration: "00:00",
isMute: false,
sliderTime: 0,
volume: 0,
};
},
computed: {
},
methods: {
init() {},
//设置慢速播放播放
changeSpeedSlow() {
if (this.multipleIndex > 0) {
this.multipleIndex--;
} else {
this.multipleIndex = 0;
}
this.$refs.audio.playbackRate = this.multipleArray[this.multipleIndex];
},
handlePlay() {
if(!this.audioFile){
return;
}
if (this.$refs.audio.paused) {
// 开始
this.showPlay = true;
this.$refs.audio.play();
} else {
// 暂停
this.showPlay = false;
this.$refs.audio.pause();
}
},
changeSpeedFast() {
if (this.multipleIndex < this.multipleArray.length - 1) {
this.multipleIndex++;
} else {
this.multipleIndex = this.multipleArray.length - 1;
}
this.$refs.audio.playbackRate = this.multipleArray[this.multipleIndex];
},
onLoadedmetadata(res) {
this.duration = util.formatSeconds(res.target.duration);
this.volume = res.target.volume * 100;
this.isMute = res.target.muted;
this.$refs.mutebar.style.backgroundSize = `${res.target.volume *100}% 100%`;
},
// 当timeupdate事件大概每秒一次,用来更新音频流的当前播放时间
onTimeupdate(res) {
this.updateProgress();
},
onVolumechange(res) {
this.$refs.audio.muted = !Boolean(res.target.volume);
this.isMute = !Boolean(res.target.volume);
},
handleProgress(e) {
let rate = e.target.value / 100;
this.$refs.audio.currentTime = this.$refs.audio.duration * rate;
this.updateProgress();
},
//更新进度条
updateProgress() {
this.sliderTime = this.$refs.audio.currentTime / this.$refs.audio.duration * 100 || 0;
this.currentTime = util.formatSeconds(this.$refs.audio.currentTime);
this.$refs.progressbar.style.backgroundSize = `${this.sliderTime}% 100%`;
},
//音量操作
hancleChangeVolume(e) {
if(!this.audioFile){
return;
}
this.volume = e.target.value;
let _volume = e.target.value / 100;
this.$refs.audio.volume = _volume;
this.$refs.mutebar.style.backgroundSize = `${e.target.value}% 100%`;
},
//静音
handleMute() {
if (this.$refs.audio.muted) {
//取消静音
this.isMute = false;
this.$refs.audio.muted = false;
} else {
//静音
this.isMute = true;
this.$refs.audio.muted = true;
}
},
//下载
handleDownload() {
if(!this.audioFile){
return;
}
const filedir = this.audioFile && this.audioFile.split("/");
let filename = filedir.length > 0 && filedir[filedir.length - 1] || "";
this.downloadVoice(this.audioFile, filename);
},
//下载文件流
downloadVoice(url, fileName) {
const a = document.createElement("a");
a.href = url; // 文件流生成的url
a.download = fileName; // 文件名
(document.body || document.documentElement).appendChild(a);
a.click();
a.remove();
},
//播放完成
onAudioEnded() {
this.sliderTime = 0;
this.currentTime = "00:00";
this.showPlay = false;
this.$refs.progressbar.style.backgroundSize = "0% 100%";
},
},
mounted() {
this.init();
},
beforeDestroy() {
clearTimeout(this.timer);
},
};
1、通过从父组件传入audioFile,获取音频文件。
2、util.formatSeconds用于转换时间转为hh:dd:ss 格式。
本文介绍了如何实现一个自定义的音频播放组件audioPlay,功能包括播放/暂停、音量控制、播放速度调整、播放进度条以及下载。该组件基于html5的<audio>标签,利用vue进行逻辑处理。详细代码包括html、css和js部分。
1万+

被折叠的 条评论
为什么被折叠?



