本文参考 https://blog.csdn.net/weixin_40404336/article/details/84570070
感谢上面博主分享,为了方便前端开发人员查阅,提供新的连接。~_~.
下面代码有个细节,slider滑块这里采用的vant,原理同上。
定义vue 文件 :vueAudio.vue,代码内容如下:(引用代码后,在其他页面导入该组件即可,不懂的可以看上面博主分享)
v-model="sliderTime" :inactive-color="'#EBEBEB'" :bar-height="'2vw'" :active-color="'#0096F0'" @change="changeCurrentTime" >
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)
return ("0" + mimute).slice(-2) + ":" + ("0" + second).slice(-2);
} else {
return "00:00";
}
}
import { Slider } from "vant";
import "vant/lib/index.css";
export default {
components: {
vanSlider: Slider
},
props: {
//音频路径
theUrl: {
type: String,
required: true
},
//播放速度 未测试
theSpeeds: {
type: Array,
default() {
return [1, 1.5, 2];
}
},
//
theControlList: {
type: String,
default: ""
}
},
name: "VueAudio",
data() {
return {
L: 0,
url: this.theUrl || "http://res01.zyxschool.com/images/ti100audio/201909/2019/1569407886_019499.mp3",
audio: {
currentTime: 0,//当前播放时间
maxTime: 0,//最大时长
playing: false, //是否自动播放
muted: false, //是否静音
speed: 1,//播放速度
waiting: true, // 处于等待状态
preload: "auto" //是否重新播放
},
sliderTime: 0, //开始播放位置,
volume: 100,//音量
speeds: this.theSpeeds, // 播放速度
controlList: {
// 不显示下载
noDownload: false,
// 不显示静音
noMuted: false,
// 不显示音量条
noVolume: false,
// 不显示进度条
noProcess: false,
// 只能播放一个
onlyOnePlaying: false,
// 不要快进按钮
noSpeed: false
}
};
},
methods: {
setControlList() {
let controlList = this.theControlList.split(" ");
controlList.forEach(item => {
// console.log(this.controlList[item]);
if (this.controlList[item] !== undefined) {
this.controlList[item] = true;
}
});
},
changeSpeed() {
let index = this.speeds.indexOf(this.audio.speed) + 1;
this.audio.speed = this.speeds[index % this.speeds.length];
this.$refs.audio.playbackRate = this.audio.speed;
},
startMutedOrNot() {
this.$refs.audio.muted = !this.$refs.audio.muted;
this.audio.muted = this.$refs.audio.muted;
},
// 音量条toolTip
formatVolumeToolTip(index) {
return "音量条: " + index;
},
// 进度条toolTip
formatProcessToolTip(index = 0) {
index = parseInt((this.audio.maxTime / 100) * index);
return "进度条: " + realFormatSecond(index);
},
// 音量改变
changeVolume(index = 0) {
this.$refs.audio.volume = index / 100;
this.volume = index;
},
// 播放跳转
changeCurrentTime(index) {
this.$refs.audio.currentTime = parseInt(
(index / 100) * this.audio.maxTime
);
},
startPlayOrPause() {
return this.audio.playing ? this.pausePlay() : this.startPlay();
},
// 开始播放
startPlay() {
this.$refs.audio.play();
},
// 暂停
pausePlay() {
this.$refs.audio.pause();
},
// 当音频暂停
onPause() {
this.audio.playing = false;
},
// 当发生错误, 就出现loading状态
onError() {
this.audio.waiting = true;
},
// 当音频开始等待
onWaiting(res) {
console.log(res);
},
// 当音频开始播放
onPlay(res) {
// console.log(res)
this.audio.playing = true;
this.audio.loading = false;
if (!this.controlList.onlyOnePlaying) {
return;
}
let target = res.target;
let audios = document.getElementsByTagName("audio");
[...audios].forEach(item => {
if (item !== target) {
item.pause();
}
});
},
// 当timeupdate事件大概每秒一次,用来更新音频流的当前播放时间
onTimeupdate(res) {
// console.log('timeupdate')
//console.log(res)
this.audio.currentTime = res.target.currentTime;
this.sliderTime = parseInt(
(this.audio.currentTime / this.audio.maxTime) * 100
);
},
// 当加载语音流元数据完成后,会触发该事件的回调函数
// 语音元数据主要是语音的长度之类的数据
onLoadedmetadata(res) {
console.log("loadedmetadata");
console.log(res);
this.audio.waiting = false;
this.audio.maxTime = parseInt(res.target.duration);
//this.audio.maxTime = parseInt( this.$refs.audio.duration);
console.log("总时间", this.$refs.audio.duration);
this.$emit("loading-true", 11);
},
add() {
//前进15s
let current_t = parseInt(this.$refs.audio.currentTime);
let total_t = parseInt(this.$refs.audio.duration);
//console.log(this.$refs.audio);
this.$refs.audio.currentTime =
current_t + 15 >= total_t ? total_t : current_t + 15;
console.log(current_t, total_t, this.$refs.audio.currentTime);
// console.log(this.$refs.audio.played);
},
minus() {
//后退15秒
let current_t = parseInt(this.$refs.audio.currentTime);
this.$refs.audio.currentTime = current_t - 15 <= 0 ? 0 : current_t - 15;
}
},
watch: {},
filters: {
formatSecond(second = 0) {
return realFormatSecond(second);
},
transPlayPause(value) {
// console.log(value);
//return value ? require("../assets/img/pause.png") : require("../assets/img/play.png")
return "123";
},
transMutedOrNot(value) {
return value ? "放音" : "静音";
},
transSpeed(value) {
return "快进: x" + value;
}
},
watch: {
url(val, oldval) {
console.log(val, oldval);
},
sliderTime(val, oldval) {
// console.log(val,oldval);
if (val >= 98) {
this.L = 98;
return;
}
this.L = val;
}
},
created() {
// let audio = new Audio();
// audio.src = this.url; //audio链接
// audio.addEventListener('loadedmetadata', function() {
// console.log(audio.duration);
// //
// });
this.setControlList();
}
};
.van-slider {
width: 100%;
}
.boxs {
display: flex;
justify-content: center;
position: fixed;
bottom: 14vw;
width: 100%;
border-bottom: 1px solid #dfdfdf;
}
.track {
background: #f8f8f8;
height: 15vw;
display: flex;
justify-content: flex-start;
align-items: center;
box-sizing: border-box;
width: 100%;
}
.times {
color: #fff;
}
.startT {
padding: 0 4vw;
color: #333333;
}
.endT {
padding: 0 4vw;
color: #333333;
}
.operation {
margin-top: 4vw;
display: flex;
justify-content: center;
align-items: center;
}
.play-bt {
font-size: 0;
width: 76px;
height: 75px;
}
.back-box {
margin-right: 50px;
}
.forward {
margin-left: 50px;
}
.back-box,
.forward {
font-size: 0;
width: 47px;
height: 46px;
}
.sliders-box {
width: 100%;
display: flex;
justify-content: center;
align-items: center;
}
.div_box {
height: 100px;
position: relative;
}
.div0 {
width: 10px;
height: 10px;
border-radius: 5px;
background: red;
position: absolute;
top: 0;
}
.main-wrap {
padding: 0;
}
.download {
color: #409eff;
margin-left: 15px;
}
.dn {
display: none;
}