前言
近期項目中經(jīng)常使用到音頻功能母廷,然而自帶的音頻控制面板大部分情況都不能滿足需
求糊肤,固用vue自定義了一個通用的的audio面板。主要功能有:播放馆揉、暫停、自定義進(jìn)度
條勤讽,靜音控制等內(nèi)容拗踢,廢話不多說,先上圖
頁面組成
- 播放暫停模塊
- 自定義進(jìn)度條模塊
- 音頻時長模塊
- 靜音控制模塊
主要思路
- 使用
ref
獲取audio元素 - 調(diào)用 audio
play
pause
方法實(shí)現(xiàn)暫停播放 - 為audio添加事件:
@canplay
@timeupdate
@ended
- 在
computed
中設(shè)置靜音和非靜音圖片資源
html
<div class="app">
<div class="dialogDetailAudio" onselectstart="return false">
<img class="dialogAudioPlay" :src="audioImg" title="播控" @click="playAudio">
<span class="dialogAudioTime">{{time}}</span>
<div class="dialogAudioProgress" ref="dialogAudioProgress" @mousedown="controlAudioProgress($event)">
<span class="progressDot" :style="dotStyle"></span>
<span class="bar" :style="progressStyle"></span>
</div>
<span class="dialogAudioDuration">{{duration}}</span>
<img class="dialogAudioListen" :src="dialogAudioListen" title="靜音" @click="listenDialogAudio">
<img class="dialogAudioDownload" src="./callRecordDownload.png" title="下載" @click="downloadCallRecord">
<audio ref="recordAudio" class="recordAudio" type="audio/mpeg"
@canplay="canPlay" @timeupdate="timeUpdate" @ended="onEnded" :src="audioUrl">
</audio>
</div>
</div>
css
* {
margin: 0;
padding: 0;
}
.dialogDetailAudio {
margin-top: 100px;
margin-left: auto;
margin-right: auto;
width: 550px;
height: 49px;
line-height: 49px;
background: rgba(255, 255, 255, 1);
box-shadow: 0px 5px 30px 0px rgba(29, 34, 54, 0.18);
border-radius: 6px;
}
.dialogAudioPlay {
display: inline-block;
position: relative;
top: 6px;
margin-left: 15px;
cursor: pointer;
width: 23px;
height: 23px;
}
.dialogAudioTime {
margin-left: 11px;
font-size: 11px;
font-weight: 400;
color: rgba(51, 51, 51, 1);
}
.dialogAudioProgress {
display: inline-block;
width: 300px;
height: 2px;
background: rgba(212, 249, 232, 1);
border-radius: 1px;
margin-left: 12px;
position: relative;
}
.progressDot {
width: 8px;
height: 8px;
border-radius: 50%;
-moz-border-radius: 50%;
-webkit-border-radius: 50%;
background-color: rgba(5, 180, 147, 1);
position: absolute;
left: 0;
top: 50%;
margin-top: -5px;
margin-left: -5px;
cursor: pointer;
}
.bar {
height: 100%;
background: rgba(5, 180, 147, 1);
border-radius: 3px;
display: inline-block;
position: absolute;
}
.dialogAudioDuration {
margin-left: 11px;
font-size: 11px;
font-weight: 400;
color: rgba(34, 34, 34, 1);
}
.dialogAudioListen,
.dialogAudioDownload {
width: 16px;
height: 13px;
cursor: pointer;
}
.dialogAudioListen {
margin-left: 8px;
}
.dialogAudioDownload {
margin-left: 5px;
}
js
var app = new Vue({
el: ".app",
data() {
return {
time: "00:00",
duration: "00:00",
progressStyle: { width: "" },
dotStyle: { left: "" },
audioUrl: "http://file.duzhai.net/Files/Audio/2017-08/af01ab05-d112-4ad7-9cff-2cfecced5bc6.mp3",
audioImg: "./dialogDetailPlay.png",
dialogAudioListenGroup: ["./callRecordListen.png", "./quite.png"],
imgIndex: 0,
}
},
//計算屬性 切換靜音圖片
computed: {
dialogAudioListen() {
return this.dialogAudioListenGroup[this.imgIndex]
}
},
methods: {
//播放暫途遥控制
playAudio() {
let recordAudio = this.$refs.recordAudio; //獲取audio元素
if (recordAudio.paused) {
this.audioImg = "./dialogDetailPause.png"
recordAudio.play();
} else {
this.audioImg = "./dialogDetailPlay.png"
recordAudio.pause();
}
},
//進(jìn)度條更新
timeUpdate() {
this.duration = this.transTime(this.$refs.recordAudio.duration);
let timeStr = parseInt(this.$refs.recordAudio.currentTime);
this.time = this.transTime(timeStr);
let scales = this.$refs.recordAudio.currentTime / this.$refs.recordAudio.duration;
this.progressStyle.width = scales * 100 + '%';
this.dotStyle.left = scales * 100 + '%';
},
//播放結(jié)束
onEnded() {
this.audioImg = "./dialogDetailPlay.png";
this.time = "00:00";
this.progressStyle.width = 0;
this.dotStyle.left = 0;
},
//用戶可以開始播放audio
canPlay() {
//獲取audio音頻文件總時長 并設(shè)置到界面并解決出現(xiàn) NAN 的問題
this.duration = this.transTime(this.$refs.recordAudio.duration);
},
//靜音控制
listenDialogAudio() {
this.imgIndex = (this.imgIndex + 1) % (this.dialogAudioListenGroup).length;
if (this.dialogAudioListen == "./quite.png") {
this.$refs.recordAudio.volume = 0;
} else {
this.$refs.recordAudio.volume = 1;
}
},
//鼠標(biāo)點(diǎn)擊移動播放進(jìn)度
controlAudioProgress(event) {
let audio = this.$refs.recordAudio;
let dialogAudioProgress = this.$refs.dialogAudioProgress;
if (!audio.paused || audio.currentTime != 0) {
let pgsWidth = parseFloat(window.getComputedStyle(dialogAudioProgress, null).width.replace('px', ''));
let rate = event.offsetX / pgsWidth;
audio.currentTime = audio.duration * rate;
this.timeUpdate();
}
},
//下載音頻
downloadCallRecord() {
console.log("下載...");
},
//時間轉(zhuǎn)換
transTime(value) {
let time = "";
let h = parseInt(value / 3600);
value %= 3600;
let m = parseInt(value / 60);
let s = parseInt(value % 60);
if (h > 0) {
time = this.formatTime(h + ":" + m + ":" + s);
} else {
time = this.formatTime(m + ":" + s);
}
return time;
},
//時間格式化
formatTime(value) {
let time = "";
let s = value.split(':');
let i = 0;
for (; i < s.length - 1; i++) {
time += s[i].length == 1 ? ("0" + s[i]) : s[i];
time += ":";
}
time += s[i].length == 1 ? ("0" + s[i]) : s[i];
return time;
}
},
})
注意點(diǎn)
-
onselectstart
禁止用戶選中網(wǎng)頁上的內(nèi)容蓄髓。
用戶點(diǎn)擊進(jìn)度條位置不會選中其他內(nèi)容 -
@canplay
設(shè)置audio總時長并防止出現(xiàn) NAN -
@ended
視頻播放完畢后應(yīng)回到初始狀態(tài) -
computed
設(shè)置靜音圖片資源。 音頻的volume
默認(rèn)值是1
寫到最后
其實(shí)陡叠,實(shí)現(xiàn)自定義內(nèi)容很簡單,主要就是界面與js邏輯控制的結(jié)合枉阵,只要弄清楚元素對應(yīng)
的API并加以改進(jìn) 就可實(shí)現(xiàn)很多想要的功能。希望本文可以幫到您兴溜,感謝。