H5 使用audio 实现语音播放 并显示语音时长 可快进、快退
以vue示例:效果<template><div class="voice-box"><audioref="audio"@pause="onPause"@play="onPlay"@timeupdate="onTimeupdate"@loadedmetadata="onL...
·
以vue示例:
效果
<template>
<div class="voice-box">
<audio
ref="audio"
@pause="onPause"
@play="onPlay"
@timeupdate="onTimeupdate"
@loadedmetadata="onLoadedmetadata"
controls="controls"
style="display:none;"
:src="imgUrl + '从后台获取的地址'"
>
<!-- <source :src="imgUrl + questionData.voiceAddress" /> -->
<!-- <source src="@/assets/测试语音.mp3" /> -->
</audio>
<!-- 音频播放控件 -->
<div>
<button @click="startPlayOrPause" class="play-btn" :class="{'btn-pause': audio.playing}"></button>
<!-- 当前时间 -->
<span class="time">{{ audio.currentTime | formatSecond}}</span>
<!-- 语音条 -->
<div class="slider-box">
<div class="slider" @touchstart="handleTouchStart">
<div class="slider-track"></div>
<div class="slider-fill" :style="'width:'+sliderTime+'%'"></div>
<div class="slider-thumb" :style="'left:'+sliderTime+'%'"></div>
</div>
</div>
<!-- 总时长 -->
<span class="time">{{ audio.maxTime | formatSecond}}</span>
</div>
</div>
</template>
<script>
// 将整数转换成 时:分:秒的格式
function realFormatSecond(second) {
var secondType = typeof second;
if (secondType === "number" || secondType === "string") {
second = parseInt(second);
var hours = Math.floor(second / 3600);
second = second - hours * 3600;
var mimute = Math.floor(second / 60);
second = second - mimute * 60;
return (
// hours + ":" + ("0" + mimute).slice(-2) + ":" + ("0" + second).slice(-2)
("0" + mimute).slice(-2) + ":" + ("0" + second).slice(-2)
);
} else {
return "00:00";
}
}
export default {
data() {
return {
imgUrl: "http://xxx",
sliderTime: 0,
audio: {
// 该字段是音频是否处于播放状态的属性
playing: false,
// 音频当前播放时长
currentTime: 0,
// 音频最大播放时长
maxTime: 0,
minTime: 0,
step: 0.1
}
};
},
methods: {
// 控制音频的播放与暂停
startPlayOrPause() {
return this.audio.playing ? this.pause() : this.play();
},
// 播放音频
play() {
this.$refs.audio.play();
},
// 暂停音频
pause() {
this.$refs.audio.pause();
},
// 当音频播放
onPlay() {
this.audio.playing = true;
},
// 当音频暂停
onPause() {
this.audio.playing = false;
},
// 当加载语音流元数据完成后,会触发该事件的回调函数
// 语音元数据主要是语音的长度之类的数据
onLoadedmetadata(res) {
this.audio.maxTime = parseInt(res.target.duration);
},
// 当timeupdate事件大概每秒一次,用来更新音频流的当前播放时间
// 当音频当前时间改变后,进度条也要改变
onTimeupdate(res) {
this.audio.currentTime = res.target.currentTime;
this.sliderTime = parseInt(
(this.audio.currentTime / this.audio.maxTime) * 100
);
},
// 进度条格式化toolTip
formatProcessToolTip(index = 0) {
index = parseInt((this.audio.maxTime / 100) * index);
return "进度条: " + realFormatSecond(index);
},
handleTouchStart(e) {
this.setValue(e.touches[0]);
document.addEventListener("touchmove", this.handleTouchMove);
document.addEventListener("touchup", this.handleTouchEnd);
document.addEventListener("touchend", this.handleTouchEnd);
document.addEventListener("touchcancel", this.handleTouchEnd);
// e.preventDefault();
// this.onDragStart(e);
},
handleTouchMove(e) {
this.setValue(e.changedTouches[0]);
},
handleTouchEnd(e) {
this.setValue(e.changedTouches[0]);
document.removeEventListener("touchmove", this.handleTouchMove);
document.removeEventListener("touchup", this.handleTouchEnd);
document.removeEventListener("touchend", this.handleTouchEnd);
document.removeEventListener("touchcancel", this.handleTouchEnd);
// this.onDragStop(e);
},
// 从点击位置更新 value
setValue(e) {
const $el = this.$el;
const { maxTime, minTime, step } = this.audio;
let value =
((e.clientX - $el.getBoundingClientRect().left) / $el.offsetWidth) *
(maxTime - minTime);
value = Math.round(value / step) * step + minTime;
value = parseFloat(value.toFixed(5));
if (value > maxTime) {
value = maxTime;
} else if (value < minTime) {
value = minTime;
}
this.$refs.audio.currentTime = value;
},
// 拖动进度条,改变当前时间,index是进度条改变时的回调函数的参数0-100之间,需要换算成实际时间
changeCurrentTime(index) {
// this.audio.playing && this.pause();
// console.log('拖动了',index,this.sliderTime,this.audio.maxTime,parseInt(index / 100 * this.audio.maxTime))
// !this.audio.playing && this.play();
this.$refs.audio.currentTime = parseInt(
(index / 100) * this.audio.maxTime
);
}
},
filters: {
// 使用组件过滤器来动态改变按钮的显示
transPlayPause(value) {
return value ? "暂停" : "播放";
},
// 将整数转化成时分秒
formatSecond(second = 0) {
return realFormatSecond(second);
}
}
};
</script>
<style lang="less">
.voice-box {
background: #ffba00;
padding: 0 20px;
.play-btn {
width: 28px;
height: 30px;
background: url("../../assets/images/listen/play.png") no-repeat center -3px;
background-size: 100% 100%;
margin-right: 20px;
&.btn-pause {
background: url("../../assets/images/listen/pause.png") no-repeat center -2px;
background-size: 100% 100%;
}
}
.time {
font-size: 20px;
}
.slider-box {
display: inline-block;
margin: 0 30px;
}
.slider {
width: 360px;
position: relative;
top: -5px;
height: 24px;
display: flex;
align-items: center;
cursor: default;
user-select: none;
outline: none;
}
.slider-track {
position: absolute;
height: 20px;
left: 0;
right: 0;
top: 50%;
margin-top: -1px;
background-color: rgba(255, 255, 255, 0.3);
}
.slider-fill {
position: absolute;
width: 20px;
height: 19px;
background-color: #fff;
left: 0;
top: 50%;
margin-top: -1px;
}
.slider-thumb {
position: absolute;
top: 85%;
width: 20px;
height: 21px;
background-color: #fff;
color: #fff;
// border-radius: 50%;
transform: translate(-50%, -50%);
cursor: pointer;
}
}
</style>
更多推荐
已为社区贡献3条内容
所有评论(0)