Vue3自定义封装音频播放组件(带拖拽进度条)
描述
该款自定义组件可作为音频、视频播放的进度条,用于控制音频、视频的播放进度、暂停开始、拖拽进度条拓展性极高。
实现效果
具体效果可以根据自定义内容进行位置调整
项目需求
- 有播放暂停按钮
- 进度条可以跟随播放丝滑更新
- 有当前播放时间和总时间可以根据播放更新当前时间
- 可以点击进度条的某一处跳转到指定处进行播放
技术栈
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="slider"><span>{{ formattedCurrentTime }}</span><div><el-slider v-model="sliderTime" :show-tooltip="false" @change="onChange"></el-slider></div><span>{{ formattedMaxTime }}</span></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,},};},computed: {formattedCurrentTime() {return formatTime(this.audio.currentTime);},formattedMaxTime() {return formatTime(this.audio.maxTime);},},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();},onChange(value) {console.log(value, "values");this.$refs.audio.currentTime = parseInt((value / 100) * this.audio.maxTime);},},
};
</script><style scoped lang="less">
.audio_wrap_content {height: 26px;border-radius: 15px;
}.cudio_control_content {margin: 0 auto;width: 90%;height: 100%;display: flex;.slider {flex: 1;width: 100%;display: flex;align-items: center;}.slider div {flex: 1;}.slider span {margin: 0 15px;font-size: 10px;color: rgba(34, 34, 34, 0.3);}justify-content: space-between;align-items: center;.state_img {width: 18px;height: 18px;margin-right: 15px;}.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>