前言
前端开发中经常会遇到实现播放音频文件的需求,本文基于mintUI封装了一个音频播放组件。
features
- 支持播放、暂停、拖动播放的功能
- 良好的移动端播放体验
- 兼容android和ios主流系统
- 兼容webview
sourceCode
<template>
<div>
<div class="audio-play-wrapper">
<i class="operate-container" :class="[isPlay ? 'pause' : '']" @click.stop="audioState($event)"></i>
<div class="time-info-container change-time">
<span class="task-text vm current-time">{{ stopTime }}</span>
</div>
<div class="time-progress-container">
<mt-range
:min="0"
:max="audioDuration"
:bar-height="8"
v-model="currentTime"
@change="processMove"
></mt-range>
</div>
<div class="time-info-container">
<span class="task-text vm current-time">{{ audioDuration | formatTime }}</span>
</div>
<audio @error="errorHandler" @loadedmetadata="loadAudioMetaData" @canplay="getDuration" class="audio" ref="iAudio" :src="audioInfo.audioUrl"></audio>
</div>
</div>
</template>
<script>
import { formatSeconds } from "@/utils/index";
import { Toast } from "mint-ui";
export default {
name: "AudioPlayMedia",
components: {},
props: {
audioInfo: {
type: Object,
default: () => {
return {
audioUrl:
"",
};
},
},
},
data() {
return {
isPlay: false,
currentTime: 0,
audioDuration: 0,
isIphone6: false,
isVertical:!window.isTablet,
};
},
created: function () {
// 解决ios10.0.1获取音频时长加倍的问题
let u = navigator.userAgent;
if(window.isIOS &&
navigator.userAgent.toLowerCase().indexOf("iphone os 10_0_1") != -1 &&
navigator.userAgent.toLowerCase().indexOf("iphone 6") != -1) {
this.isIphone6 = true;
}
},
mounted() {
},
computed: {
stopTime: function () {
return formatSeconds(this.currentTime);
},
},
filters: {
formatTime(time) {
return formatSeconds(time);
}
},
methods: {
audioState: function (event) {
if (this.isPlay) {
this.isPlay = !this.isPlay;
let audio = this.$refs.iAudio;
audio.pause();
return;
}
this.$eventBus.$emit("audioStateChanged",event.target.id);
// 点击播放或暂停
let _this = this;
_this.isPlay = !_this.isPlay;
let audio = this.$refs.iAudio;
if (this.isPlay) {
audio.addEventListener("ended", function () {
_this.isPlay = false;
});
audio.addEventListener("timeupdate", function (currentValue) {
_this.currentTime = Math.ceil(_this.$refs.iAudio.currentTime);
});
audio.play();
}
},
// 暂停音频
pauseAudio: function(id) {
if (id !== this.audioInfo.audioUrl) {
this.isPlay = false;
let audio = this.$refs.iAudio;
audio.pause();
}
},
processMove: function (time) {
// 拖动进度条
let audio = this.$refs.iAudio;
audio.currentTime = time;
this.currentTime = time;
},
getDuration:function() {
},
loadAudioMetaData: function() {
let mDuration = this.$refs.iAudio.duration;
this.audioDuration = Math.ceil(this.isIphone6 ? mDuration / 2: mDuration);
},
errorHandler: function() {
}
},
destroyed() {},
};
</script>
<style lang="scss" scoped>
/**音频播放器样式 */
.audio-play-container {
padding: rem(23px) rem(36px);
border-radius: rem(11px);
border: 1px solid #f0f1f4;
.audio-play-wrapper {
display: flex;
align-items: center;
justify-content: space-between;
.operate-container {
display: inline-block;
width: rem(60px);
height: rem(60px);
background: url("../../../assets/images/answer/audio-play.png") no-repeat
center;
background-size: contain;
&.pause {
background: url("../../../assets/images/answer/pause.png") no-repeat
center;
background-size: contain;
}
}
.operate-container-across {
width: rem(40px);
height: rem(40px);
}
.time-progress-container {
flex: 1;
margin: 0px rem(24px);
}
.time-info-container {
color: #8c8c8c;
font-size: rem(24px);
&.change-time {
margin-left: rem(32px);
}
}
}
.current-time {
font-size: 16px;
}
}
.audio-play-container-across {
padding: rem(16px) rem(36px);
}
</style>
<style lang="scss">
// mt-range控件样式
.time-progress-container {
.mt-range {
.mt-range-content {
.mt-range-runway {
border-radius: 4px;
border-top-color: #f0f1f4;
right: -10px;
}
.mt-range-progress {
background-color: #00baff;
border-top-left-radius: 4px;
border-bottom-left-radius: 4px;
}
.mt-range-thumb {
top: 50%;
transform: translateY(-50%);
width: 12px;
height: 12px;
background: rgba(255, 255, 255, 1);
box-shadow: 0px 1px 3px 0px rgba(0, 0, 0, 0);
border: 1px solid rgba(0, 186, 255, 1);
}
}
}
}
</style>
存在的问题
- 在ihone的10.0.1系统上获取的音频总时长是真实时长的两倍(很诡异)
- mt-range只支持拖曳快进,不支持点击快进
- el-slider支持点击快进,不支持拖曳快进