<template>
<div class="musicPlay" v-if="audioVisible">
<!-- ref="audio" -->
<audio
ref="audio"
id="course-aud"
@play="playFunc"
@pause="pauseFunc"
@timeupdate="timeupdateFunc"
@canplay="canplayFunc"
@error="errorFunc"
:src="audioSrc"
>
</audio>
<div class="audioControl">
<div class="errorMask" v-show="isError">{{ errorMsg }}</div>
<p class="audioClose" @click="audioVisible = false">x</p>
<p>{{ customerName }}</p>
<div
style="display: flex; align-items: center"
@mousedown="isDraging = true"
@mouseup="isDraging = false"
>
<el-slider
v-model="playProcess"
class="sliderClass"
style="width: 80%"
@change="setProcessFunc"
:format-tooltip="formatTooltip"
></el-slider>
<div style="color: #333; width: 120px; text-align: right">
{{ formatCurrentTime }} / {{ formatDuration }}
</div>
</div>
<div class="playControl">
<span
class="audioSpan"
@click="clickFunc('play')"
v-show="!isPlaying"
style="width: 10px"
><i class="el-icon-video-play" aria-hidden="true"></i
></span>
<span
class="audioSpan"
@click="clickFunc('pause')"
v-show="isPlaying"
style="width: 10px"
><i class="el-icon-video-pause" aria-hidden="true"></i
></span>
<span
class="audioSpan"
@click="clickFunc('backward')"
style="width: 10px;margin-right: 15px;"
><i class="el-icon-d-arrow-left" aria-hidden="true"></i
></span>
<span class="audioSpan" style="margin-right: 10px;">
<span class="speed">X {{ playSpeed | fmtPlaySpeed() }}</span>
</span>
<span
class="audioSpan"
@click="clickFunc('forward')"
style="width: 10px"
><i class="el-icon-d-arrow-right" aria-hidden="true"></i
></span>
<!-- <span
class="audioSpan"
@click="clickFunc('refresh')"
style="width: 10px"
><i class="el-icon-refresh" aria-hidden="true"></i
></span> -->
<!-- <span class="audioVolSpan" style="width: 10px"
><i class="el-icon-microphone" aria-hidden="true"></i
></span> -->
<!-- <el-slider
v-model="playVolume"
class="sliderVolumClass"
:format-tooltip="formatTooltipVol"
@change="setVolumeFunc"
></el-slider> -->
</div>
</div>
</div>
</template>
<script>
// import { mapState } from "vuex";
function toStringFunc (param) {
if (param > 9) {
return param + ''
} else {
return '0' + param
}
}
export default {
name: 'CustomAudio',
props: {
customerName: {
type: String,
default: ''
}, // 父组件传递过来的音频名称
audioSrc: {
type: String,
default: ''
}, // 父组件传递的音频链接
audioVisible: {
type: Boolean,
default: false
} // 控制音频组件的显示与隐藏
},
data () {
return {
musicUrl: '',
isPlaying: false,
isError: false,
src: '',
playProcess: 0,
playVolume: 50,
playSpeed: 1,
totalTimes: '00:00',
currentTime: '00:00',
errorMsg: '音频加载失败,无法播放!',
isDraging: false
}
},
watch: {
audioSrc (nVal, oVal) {
this.src = nVal
}
},
filters: {
fmtPlaySpeed (pSpeed) {
return pSpeed.toFixed(1)
}
},
computed: {
formatDuration () {
if (typeof this.totalTimes === 'number') {
const fTotal = Math.floor(this.totalTimes)
const tempMin = Math.floor(fTotal / 60)
const tempSec = fTotal % 60
// const min, sec
return `${toStringFunc(tempMin)} : ${toStringFunc(tempSec)}`
}
return '00:00'
},
formatCurrentTime () {
if (typeof this.currentTime === 'number') {
const fTotal = Math.floor(this.currentTime)
const tempMin = Math.floor(fTotal / 60)
const tempSec = fTotal % 60
// const min, sec;
return `${toStringFunc(tempMin)} : ${toStringFunc(tempSec)}`
}
return '00:00'
}
},
methods: {
load () {
this.$refs.audio.load()
},
play () {
this.$refs.audio.play()
},
pause () {
this.$refs.audio.pause()
},
mousedownFunc () {
this.isDraging = true
},
mouseupFunc () {
this.isDraging = false
},
formatTooltip (val) {
const currTime = Math.floor((val / 100) * this.totalTimes)
const tempMin = Math.floor(currTime / 60)
const tempSec = currTime % 60
// const min, sec;
return `${toStringFunc(tempMin)} : ${toStringFunc(tempSec)}`
},
formatTooltipVol (vol) {
return Math.round(((vol * 2) / 100) * 10) / 10
},
clickFunc (val) {
if (val === 'play') {
this.isPlaying = !this.isPlaying
this.$refs.audio.play()
} else if (val === 'pause') {
this.isPlaying = !this.isPlaying
this.$refs.audio.pause()
} else if (val === 'backward') {
// 加快音频播放速度,速率范围[0.5,2]
if (this.playSpeed > 0.5) {
this.playSpeed -= 0.5
this.$refs.audio.playbackRate = this.playSpeed
}
} else if (val === 'forward') {
// 减慢音频播放速度,速率范围[0.5,2]
if (this.playSpeed < 2) {
this.playSpeed += 0.5
this.$refs.audio.playbackRate = this.playSpeed
}
} else if (val === 'refresh') {
this.$refs.audio.playbackRate = 1
this.playSpeed = 1
this.$refs.audio.load()
this.$refs.audio.play()
}
},
setProcessFunc (val) {
this.$refs.audio.currentTime = Math.round((val / 100) * this.totalTimes)
this.$refs.audio.play()
},
setVolumeFunc (vol) {
// 设置播放音量,audio音量范围[0,1]
this.$refs.audio.volume = Math.round((vol / 100) * 10) / 10
},
playFunc (e) {
// console.log('music is playing')
this.isPlaying = true
this.$emit('play', this.isPlaying)
},
pauseFunc (e) {
// console.log('music is paused')
this.isPlaying = false
this.$emit('pause', this.isPlaying)
},
timeupdateFunc (e) {
if (!this.isDraging) {
this.playProcess = (e.target.currentTime / this.totalTimes) * 100
this.currentTime = e.target.currentTime
}
this.$emit('timeupdate', this.currentTime, this.playProcess)
},
canplayFunc (e) {
// console.log('music can be played')
this.isError = false
this.$refs.audio.volume = 0.5
this.totalTimes = e.target.duration // 无
console.log(e.target.duration, 'duration')
},
errorFunc (e) {
// console.log('music load error!')
this.isError = true
}
}
}
</script>
<style scoped lang="less">
::v-deep .el-slider__runway {
height: 4px;
.el-slider__bar {
height: 4px;
}
}
::v-deep.el-slider__button-wrapper {
height: 20px;
width: 20px;
top: -10px;
.el-slider__button {
width: 12px !important;
height: 12px !important;
}
}
.musicPlay {
display: flex;
// justify-content: center;
// margin-bottom: 400px;
// .sliderClass,
// .audioControl {
// position: relative;
// }
.audioControl {
// position: fixed;
// left: 15%;
// bottom: 0%;
width: 700px;
height: 80px;
border-radius: 50px;
padding: 0 50px;
background-color: #f2f2f2;
.errorMask {
color: #e6a23c;
text-align: center;
width: 100%;
height: 100%;
position: absolute;
top: 0;
left: 0;
z-index: 999;
}
.audioClose{
position: absolute;
top:-10%;
right: 3%;
font-size: 25px;
}
p {
color: #333;
margin: 12px 0 0 0;
}
.playControl {
display: flex;
align-items: center;
user-select: none;
// margin-top: 5px;
.audioSpan,
.audioVolSpan {
color: #333;
font-size: 20px;
margin-right: 30px;
cursor: pointer;
&:hover {
color: #999;
}
.audioIcon {
font-size: 28px;
}
.speed {
font-size: 16px;
}
.volume {
font-size: 18px;
}
}
.audioVolSpan {
margin-right: 10px;
margin-left: 32%;
}
.sliderVolumClass {
display: inline-block;
width: 25%;
.el-slider__runway {
margin: 0;
}
}
}
}
}
/deep/.el-slider__button {
border: 2px solid #333;
}
/deep/.el-slider__bar {
background: #333;
}
</style>
自定义audio组件
于 2023-02-15 15:20:51 首次发布