Vue自定义封装音频播放组件(带拖拽进度条)
描述
该款自定义组件可作为音频、视频播放的进度条,用于控制音频、视频的播放进度、暂停开始、拖拽进度条拓展性极高。
实现效果
具体效果可以根据自定义内容进行位置调整
项目需求
- 有播放暂停按钮
- 进度条可以跟随播放丝滑更新
- 有当前播放时间和总时间可以根据播放更新当前时间
- 可以点击进度条的某一处跳转到指定处进行播放
技术栈
vue2/vue3+elementUI || elementPlus || vant
功能实现
<template>
<div class="audio_wrap_content" :style="[{ backgroundColor: bgColor }]">
<audio
ref="audio"
@play="playFunc"
@pause="pauseFunc"
@timeupdate="timeupdateFunc"
@loadedmetadata="onLoadedmetadata"
@ended="handleEnd"
>
<source :src="audioSrc" />
</audio>
<div class="cudio_control_content">
<img
@click="startPlayOrPause"
class="state_img"
:src="audio.playing ? stopImg : playImg"
alt=""
/>
<div class="state_time" style="marginRight:5px">{{audio.currentTime | formatSecond}}</div>
<div class="slider">
<el-slider v-model="sliderTime" :show-tooltip="false" @change="onChange"></el-slider>
</div>
<!-- 这块代码是移动端的vant组件库可用于移动端H5 (如要用此代码则需要将css中的.slider:flex:1去掉 并将slider类名div注释即可) -->
<!-- <van-slider
v-model="sliderTime"
bar-height="1px"
active-color="#ffb900"
button-size="4px"
@change="onChange"
>
<template #button>
<div class="custom-button"></div>
</template>
</van-slider> -->
<div class="state_time" style="marginLeft:5px">{{audio.maxTime | formatSecond}}</div>
</div>
</div>
</template>
<script>
function formatTime(second) {
let m = parseInt(second / 60);
let s = parseInt(second % 60);
let formatTime = "";
if(second==0){
return "0'00''"
}
if (m == 0) {
if(s>=10){
formatTime = "0'"+ s + "''";
}else{
formatTime = "0'0"+ s + "''";
}
} else {
if(s>=10){
formatTime = m + "'" + s + "''";
}else{
formatTime = m + "'0" + s + "''";
}
}
return formatTime
}
export default {
name: "AudioPlay",
props: {
bgColor: {
type: String,
default: "rgba(255,255,255,0.15)",
},
audioSrc: {
type: String,
default: require("@/assets/music/offer_des.mp3"),
},
themeColor: {
type: String,
default: "#ffb900",
},
},
data() {
return {
value1:1,
playImg: require("@/assets/images/play.png"),
stopImg: require("@/assets/images/stop.png"),
sliderTime: 0,
audio: {
maxTime: 0 /* 音频最大播放时长 */,
currentTime: 0 /* 当前播放时长 */,
playing: false /* 音频当前处于播放/暂停状态 */,
},
};
},
methods: {
/* 播放音频 */
play() {
console.log("触发 播放");
this.$refs.audio.play();
},
/* 暂停音频 */
pause() {
this.$refs.audio.pause();
},
/** 当音乐播放 */
playFunc() {
this.audio.playing = true;
},
/** 当音乐暂停 */
pauseFunc() {
this.audio.playing = false;
},
/** 当音乐结束 */
handleEnd(){
this.sliderTime = 0
this.audio.playing = false
this.audio.currentTime = 0
},
/* 每秒触发一次 用来更新当前播放时间 */
timeupdateFunc(res) {
this.audio.currentTime = res.target.currentTime
/* 当音频播放时 进度条也要随之改变 */
this.sliderTime = parseInt(this.audio.currentTime / this.audio.maxTime * 100)
},
/* 音频加载完成后的回调函数 */
onLoadedmetadata(res) {
console.log(111,'首次加载完成');
this.audio.maxTime = parseInt(res.target.duration);
},
/* 控制音频播放、暂停 */
startPlayOrPause() {
console.log("bof",'暂停-播放');
this.audio.playing ? this.pause() : this.play();
},
/* 拖动进度条,改变当前时间 value是进度条改变时的回调函数的参数 值为0~100之间,需要换算成实际时间 */
onChange(value){
console.log(value,'values');
this.$refs.audio.currentTime = parseInt(value / 100 * this.audio.maxTime)
// console.log(this.$refs.audio.currentTime , 'this.$refs.audio.currentTime ');
}
},
filters: {
formatSecond(second=0){
return formatTime(second)
}
},
};
</script>
<style scoped lang="less">
.audio_wrap_content {
// width: 180px;
height: 26px;
border-radius: 15px;
// transform: translateX(-25px);
}
.cudio_control_content {
margin: 0 auto;
width: 90%;
height: 100%;
display: flex;
.slider{
flex:1
}
justify-content: space-between;
align-items: center;
.state_img {
width: 18px;
height: 18px;
}
.custom-button {
width: 8px;
background-color: #ffb900;
height: 8px;
border-radius: 8px;
}
.state_time {
font-family: "BIGJOHN";
font-size: 10px;
color: rgba(34, 34, 34, 0.3);
margin-right: 3px;
margin-left: 3px;
}
}
</style>