<template>
<div class="container">
<audio
ref="audio"
controls
:src="src"
style="display: none"
@canplay="bofang"
@timeupdate="timeupdate"
></audio>
<div class="myAudio">
<img
v-if="playing"
class="imgLB"
style="width: 16px"
src="https://img0.baidu.com/it/u=933426644,47345326&fm=253&fmt=auto&app=138&f=JPEG"
alt=""
@click="onPause()"
/>
<img
v-else
class="imgLB"
style="width: 16px"
src="https://img1.baidu.com/it/u=1308789919,755843987&fm=253&fmt=auto&app=138&f=JPEG"
alt=""
@click="onPlay()"
/>
<div class="progress">
<el-slider
v-model="value"
:show-tooltip="false"
@change="change"
@mousedown.native="isChange = true"
@mouseup.native="isChange = false"
></el-slider>
</div>
<div class="nowTime">{{ nowTime }}</div>
<div>|</div>
<div class="allTime">{{ allTime }}</div>
<div v-click-outside="handleClickOutvolumeView" class="volumeView">
<img
class="imgLB"
style="width: 14px"
src="https://bpic.51yuansu.com/pic3/cover/01/22/90/59224a03eabfa_610.jpg"
alt=""
@click="openVolume"
/>
<div v-show="showVolume" class="volumeSlider">
<div class="volumeValue">{{ volumeValue }}</div>
<el-slider
v-model="volumeValue"
:show-tooltip="false"
vertical
height="100px"
@change="changeVol"
>
</el-slider>
</div>
</div>
<div v-click-outside="handleClickOutsideSpeed" class="openSpeed" @click="toOpenSpeed">
<div class="speedText">倍速 {{ speed }}</div>
<div v-show="openSpeed" class="speedSelect">
<div
v-for="(item, index) in speedOptions"
:key="index"
class="itemspeed"
@click.stop="selectSpeed(item)"
>
{{ item.label }}
</div>
</div>
</div>
</div>
</div>
</template>
<script>
/*
音频播放组件指引:
1.引用组件
2.通过props传入src音频地址,例:<myAudio ref="audio" :src="http://.....mp3" />
3.若需关闭音频,可通过ref调用onPause()方法,例:this.$refs.audio.onPause();
4.若需关闭音频后将进度条重置,可通过ref调用resetTime()方法
*/
export default {
directives: {
'click-outside': {
bind(el, binding, vnode) {
console.log('bind');
function eventHandler(e) {
if (el.contains(e.target)) {
return false;
}
// 如果绑定的参数是函数,正常情况也应该是函数,执行
if (binding.value && typeof binding.value === 'function') {
binding.value(e);
}
}
// 用于销毁前注销事件监听
el.__click_outside__ = eventHandler;
// 添加事件监听
document.addEventListener('click', eventHandler);
},
unbind(el, binding, vnode) {
console.log('unbind');
// 移除事件监听
document.removeEventListener('click', el.__click_outside__);
// 删除无用属性
delete el.__click_outside__;
},
},
},
props: {
src: {
default: 'http://music.163.com/song/media/outer/url?id=1337065812.mp3',
type: String,
},
},
data() {
return {
playing: false,
value: 0,//播放时间进度条
volumeValue: 0, //音量
showVolume: false, //显示音量
max: 0,
allTime: '00:00',
nowTime: '00:00',
speed: '1.0×',
openSpeed: false,
//判断是否被拖动
isChange: false,
speedOptions: [
{
value: 0.5,
label: '0.5×',
},
{
value: 0.75,
label: '0.7×',
},
{
value: 1,
label: '1.0×',
},
{
value: 1.5,
label: '1.5×',
},
{
value: 2,
label: '2.0×',
},
{
value: 3,
label: '3.0×',
},
],
};
},
created() {},
mounted() {},
methods: {
change() {
if (this.max === 0) return;
this.$refs.audio.currentTime = (this.value / 100) * this.max;
this.isChange = false;
},
bofang() {
this.max = this.$refs.audio.duration;
this.allTime = this.timeFormat(this.max);
this.volumeValue = this.$refs.audio.volume * 100;
console.log(this.$refs.audio.duration);
},
timeupdate() {
if (this.isChange === true) return;
this.value = (this.$refs.audio.currentTime / this.max) * 100;
this.nowTime = this.timeFormat(this.$refs.audio.currentTime);
},
// 音频播放
onPlay() {
this.playing = true;
console.log('音频播放');
this.$refs.audio.play();
},
// 当音频暂停
onPause() {
this.playing = false;
console.log('音频暂停');
this.$refs.audio.pause();
},
//将单位为秒的的时间转换成mm:ss的形式
timeFormat(number) {
var minute = parseInt(number / 60);
var second = parseInt(number % 60);
minute = minute >= 10 ? minute : '0' + minute;
second = second >= 10 ? second : '0' + second;
return minute + ':' + second;
},
toOpenSpeed() {
this.openSpeed = true;
},
selectSpeed(item) {
this.$refs.audio.playbackRate = item.value;
this.openSpeed = false;
this.speed = item.label;
},
openVolume() {
this.showVolume = true;
},
//改变音量
changeVol(val) {
this.$refs.audio.volume = val / 100;
this.showVolume = false;
},
handleClickOutvolumeView() {
this.showVolume = false;
},
handleClickOutsideSpeed() {
this.openSpeed = false;
},
//将进度条归零
resetTime() {
this.$refs.audio.currentTime = 0;
},
},
};
</script>
<style lang="scss" scoped>
.container {
font-size: 12px;
}
.myAudio {
width: 320px;
height: 46px;
border: 1px solid #d9d9d9;
display: flex;
align-items: center;
padding: 0 10px;
background-color: #fffffe;
border-radius: 3px;
color: #8c8c8c;
.progress {
width: 120px;
margin: 0 10px 0 10px;
::v-deep .sp-slider__button-wrapper {
width: 20px;
height: 20px;
margin-top: 8px;
}
::v-deep .sp-slider__button {
width: 12px;
height: 12px;
background-color: #4974f5;
}
}
.nowTime {
margin-right: 3px;
white-space: nowrap;
}
.allTime {
margin: 0 5px 0 3px;
white-space: nowrap;
}
.volumeView {
position: relative;
display: flex;
justify-content: center;
align-items: center;
margin-right: 3px;
.imgLB {
width: 20px;
}
.volumeSlider {
position: absolute;
bottom: 22px;
left: -8px;
background: #fff;
border-radius: 5px;
box-shadow: 0 0 10px #8c8c8c;
padding: 0px 0 10px 0;
.volumeValue {
margin: 10px 0;
text-align: center;
}
}
}
.openSpeed {
position: relative;
.speedText {
white-space: nowrap;
}
.speedSelect {
position: absolute;
background: #fff;
padding-left: 5px;
bottom: 28px;
box-shadow: 0 0 10px #8c8c8c;
border-radius: 3px;
.itemspeed {
width: 40px;
line-height: 18px;
}
.itemspeed:hover {
background-color: #ecf1fd;
}
}
}
}
</style>
封装audio,自定义样式,倍速,进度条,音量控制,无脑直接使用
于 2023-03-08 15:05:23 首次发布