实现效果:
代码实现:
<!-- 选择题听录音组件 -->
<template>
<div class="container-listening-record">
<img style="width: 1.32rem;height:1.24rem;" src="../assets/images/secondary/lesting.png" alt="">
<div class="tip-box">
<div class="tip-describe">
<span style="font-weight: 700;">tips:</span>
<span><br>Section A. Listen and answer the questions
A1.Listen to the following statements,and choose the correct picture for each question.
You are going to listen to each statement <i style="color: #4581e1;font-weight: blob;">twice</i></span>
</div>
<div class="message" style="font-weight: 700; text-align: left;">
<span>Statement 1. (第1小题,先听完录音再答题)</span>
</div>
</div>
<p><span>可播放次数:</span><span style="color: #4581e1;font-weight: blob;">{{ count }}</span></p>
<div class="btn-trim">
<!-- <tiny-button type="primary" :disabled="disabled" :icon="iconStartCircle" @click="Play"> Play </tiny-button> -->
<span>{{ starTime }} / {{ endTime }}</span>
<audio src="" :muted="muted"></audio>
</div>
<tiny-drawer title="音频将在倒计时完成后自动播放" :placement="placement" v-model:visible="visible">
<div style="height: 200px; text-align: center">
<br />
<br />
<span class="maxSizeBlob">{{ countNum }}</span>
</div>
</tiny-drawer>
</div>
</template>
<script lang="ts" setup>
import { ref, reactive, toRefs, watch, onMounted } from 'vue'
import { Button as TinyButton, Drawer as TinyDrawer } from '@opentiny/vue'
// import { IconStartCircle, IconPauseCircle } from '@opentiny/vue-icon'
// 接收父组件传递的信息
const props = defineProps({
isLesteningRecord: Boolean,
})
// 将赴组件传递的值
const { isLesteningRecord } = toRefs(props)
const countNum = ref(3)//n秒后播放音频
// 自组件传递给父组件值
const emits = defineEmits(['changeIsLesteningRecord'])
// 抽屉的显示隐藏控制
const visible = ref(false)
// 抽屉的显示位置
const placement = ref('bottom')
// 播放按钮的icon
// const iconStartCircle = IconStartCircle()
// const iconPauseCircle = IconPauseCircle()
const count = ref(1)//音频播放次数
// const disabled = false
const muted = ref<boolean>(true)
const starTime = ref('00:00')
const endTime = ref('00:00')
// watch监听
watch(isLesteningRecord, (newVal, oldVal) => {
console.log(newVal, oldVal)
visible.value = newVal
if (newVal == true) {
let t1 = setInterval(function () {
countNum.value = countNum.value - 1
if (countNum.value == 0) {
window.clearTimeout(t1) // 去除定时器
// emits('changeIsLesteningRecord')
// 关闭抽屉组件
visible.value = false
play()
}
}, 1000)
}
});
// 播放音频
function play(){
const audio = document.querySelector('audio') as HTMLAudioElement
audio.style.display = 'none'
audio.src = require('../assets/images/secondary/test.mp3')
audio?.play()
muted.value = false
}
onMounted(()=>{
const audio = document.querySelector('audio') as HTMLAudioElement
muted.value = true
// 监听音频是否加载完毕
audio.addEventListener('canplay',function(){
// console.log(audio.duration)
let timeDisplay = Math.floor(audio.duration)//获取当前播放的时间
// 处理时间分钟
let minute = parseInt(timeDisplay / 60 +'')
let minutes:any = minute
if(minute < 10){
minutes = '0' + minute
}
// 处理秒数
let second = timeDisplay % 60
let seconds:any = Math.round(second)
if(seconds < 10){
seconds = '0' + seconds
}
// console.log(minutes+'/'+seconds)
endTime.value = minutes+':'+seconds
})
// 监听音频是否播放完毕
audio.addEventListener('ended', function () {
muted.value = true
if(count.value==0){
return
}
count.value = count.value-1
play()
}, false);
// 监听当前播放到第几秒
audio.addEventListener('timeupdate', function () {
// console.log(audio.duration)
// console.log(audio.currentTime)
let timeDisplay = Math.floor(audio.currentTime)//获取当前播放的时间
// 处理时间分钟
let minute = parseInt(timeDisplay / 60 +'')
let minutes:any = minute
if(minute < 10){
minutes = '0' + minute
}
// 处理秒数
let second = timeDisplay % 60
let seconds:any = Math.round(second)
if(seconds < 10){
seconds = '0' + seconds
}
// console.log(minutes+'/'+seconds)
starTime.value = minutes+':'+seconds
}, false);
})
</script>
<style lang="scss" scoped>
.container-listening-record {
width: 100%;
// border: 1px solid red;
text-align: center;
font-size: .11rem;
.tip-box {
width: 4.83rem;
height: 1.13rem;
margin: 0 auto;
opacity: 1;
border-radius: .21rem;
background: rgba(255, 255, 255, 0.09);
box-shadow: 0rem .01rem .03rem rgba(0, 0, 0, 0.25);
backdrop-filter: blur(.03rem);
box-sizing: border-box;
padding: .15rem .22rem .22rem .26rem;
display: flex;
flex-direction: column;
justify-content: space-between;
margin-bottom: .1rem;
.tip-describe {
display: flex;
span {
display: block;
&:nth-child(2) {
box-sizing: border-box;
padding-left: .14rem;
text-align: left;
}
}
}
}
.btn-trim {
display: flex;
align-items: center;
justify-content: center;
font-size: .1rem;
font-weight: normal;
height: .18rem;
margin-top: .14rem;
.tiny-button {
width: .72rem;
height: .18rem;
// margin: 0 auto;
font-size: .08rem;
border-radius: .1rem;
font-weight: 700;
margin-top: .04rem;
margin-right: .04rem;
}
::v-deep .tiny-svg {
width: .1rem !important;
height: .1rem !important;
}
}
}
</style>