<template>
<div class="audioCan">
<canvas width="800" height="400" class="canStyle" id="myCanvas"></canvas>
<div class="audioSty"><audio id="audio" controls autoplay loop></audio></div>
<div :style="{color:btnColor,cursor:'pointer'}" v-on:click="btnClick">{{audioBtn}}</div>
<div class="audioSty" v-on:click="playMusic">播放音频文件</div>
</div>
</template>
<script>
export default({
name:"audioMedia",
data(){
return{
audioBtn:"不支持",
btnColor:"#808080",
userMedia:false,
aContext:null,
audioStream:null,
audioSource:null,
oCanvas:null,
ocanContext:null,
canColor:null,
canColor2:null,
recorder:null,
analyser:null,
animationFr:-1,
audioElem:null
}
},
watch:{
audioBtn:function(newValue,oldValue){
if(newValue == "不支持"){
this.btnColor = "#808080";
}else if(newValue == "开启麦克风"){
this.btnColor = "green";
}else if(newValue == "关闭麦克风"){
this.btnColor = "#000";
}else if(newValue == "打开麦克风异常"){
this.btnColor = "red";
}
}
},
methods:{
btnClick:function(){
this.initAudio();
this.closeAudio();
if(!this.audioStream){
this.openAudio();
}
},
initAudio:function(){
if(!this.aContext){
let tA = window.AudioContext || window.webkitAudioContext || window.mozAudioContext || window.msAudioContext;
this.aContext = new tA();
this.analyser = this.aContext.createAnalyser();
this.analyser.fftSize = 512;
}
if(!this.oCanvas){
this.oCanvas = document.getElementById("myCanvas");
this.ocanContext = this.oCanvas.getContext("2d");
this.canColor = this.ocanContext.createLinearGradient(this.oCanvas.width0.5,0,this.oCanvas.width0.5,300);
this.canColor.addColorStop(0,"#BE77FF");
this.canColor.addColorStop(0.5,"#FF0000");
this.canColor.addColorStop(1,"#FF60AF");
//倒影渐变
this.canColor2 = this.ocanContext.createLinearGradient(this.oCanvas.width0.5,300,this.oCanvas.width0.5,600);
this.canColor2.addColorStop(0,"#FFD9EC");
this.canColor2.addColorStop(0.5,"#FFAAD5");
this.canColor2.addColorStop(1,"#FF79BC");
}
},
playMusic:function(){
let sel,fileElem;
this.initAudio();
this.closeAudio();
this.audioElem = document.getElementById('audio');
this.audioElem.crossOrigin = 'anonymous';
sel = this;
fileElem = document.createElement("input");
fileElem.type = "file";
fileElem.accept = "audio/mpeg";
fileElem.click();
fileElem.onchange = function(){
let tFile,oReader;
tFile = this.files[0];
if(!tFile)return;
sel.audioElem.src = "";
oReader = new FileReader();
oReader.readAsDataURL(tFile);
oReader.onload = function(){
sel.audioElem.src = oReader.result;
sel.audioSource = sel.aContext.createMediaElementSource(sel.audioElem);
sel.audioSource.connect(sel.analyser);
sel.analyser.connect(sel.aContext.destination);
sel.getFrameData();
}
};
},
openAudio:function(){
if(!this.userMedia) return;
if(!this.aContext) return;
let sel = this;
window.navigator.mediaDevices.getUserMedia({video:false,audio:{
noiseSuppression:true,
channelCount:1,
echoCancellation:true
}}).then(function(stream){
sel.audioStream = stream;
sel.audioSource = sel.aContext.createMediaStreamSource(stream);
sel.audioSource.connect(sel.analyser);
sel.analyser.connect(sel.aContext.destination);
sel.audioBtn = "关闭麦克风";
sel.getFrameData();
}).catch(function(err){
sel.audioBtn = "打开麦克风异常";
});
},
closeAudio:function(){
let tracks;
if(this.animationFr)cancelAnimationFrame(this.animationFr);
if(this.analyser)this.analyser.disconnect();
if(this.audioSource)this.audioSource.disconnect();
if(this.audioStream){
tracks = this.audioStream.getAudioTracks();
for(var i = 0;i < tracks.length;i++){
tracks[i].stop();
}
}
if(this.audioElem)this.audioElem.src = "";
this.audioStream = null;
this.audioBtn = "开启麦克风";
},
getFrameData:function(){
let frameData,len;
len = this.analyser.frequencyBinCount;
frameData = new Uint8Array(len);
this.analyser.getByteFrequencyData(frameData);
this.draw(frameData);
this.animationFr = window.requestAnimationFrame(this.getFrameData);
},
draw:function(audioData){
let step,tValue,num,tWidth,tHeight,rectH;
num = 60;
tWidth = this.oCanvas.width;
tHeight = this.oCanvas.height;
rectH = parseInt(tHeight/2);
step = Math.round(audioData.length/num);
this.ocanContext.clearRect(0, 0, tWidth, tHeight);
this.ocanContext.beginPath();
for (var i = 1; i <= num; i++) {
tValue = audioData[step*i];
//为画笔设置填充渐变
this.ocanContext.fillStyle = this.canColor;
//由画布中间向两边画矩形
this.ocanContext.fillRect(tWidth*0.5-(i-1)*10, rectH,7,(-tValue)+1);//左边
this.ocanContext.fillRect(i*10 + tWidth*0.5,rectH,7,(-tValue)+1);//右边
this.ocanContext.fill();
//画倒影
this.ocanContext.fillStyle = this.canColor2;
this.ocanContext.fillRect(tWidth*0.5-(i-1)*10,rectH,7,tValue+1);
this.ocanContext.fillRect(i*10 + tWidth*0.5,rectH,7, tValue+1);
this.ocanContext.fill();
}
},
destroy:function(){
this.closeAudio();
if(this.aContext)this.aContext.close();
}
},
mounted:function(){
if(window.navigator.mediaDevices && window.navigator.mediaDevices.getUserMedia){
this.userMedia = true;
}else if(window.navigator.getUserMedia || window.navigator.webkitGetUserMedia ||
window.navigator.mozGetUserMedia || window.navigator.msGetUserMedia){
this.userMedia = true;
}
if(this.userMedia){
this.audioBtn = "开启麦克风";
}else{
this.audioBtn = "不支持";
}
},
beforeDestroy:function(){
this.destroy();
}
})
</script>
<style scoped>
div{
margin: 10px 0px 10px 0px;
}
.audioCan{
width: 1300px;
height: 400px;
margin: 0 auto;
margin-bottom: 50px;
}
.canStyle{
width: 100%;
height: 400px;
}
.audioSty{
margin: 0 auto;
}
</style>