今天看个类似微信音频播放器的效果:
简单使用
使用比较简单,直接配置如下:
varwx_audio=newWxAudio({
ele:".wx-audio",
title:music[0].title,
disc:music[0].descr,
src:music[0].src,
loop:0,
width:"320px",
ended:function(){
wx_audio.audioCut(music[1].src,music[1].title,music[1].descr)
},
});
一些API如下:
document.getElementById("play").onclick=function(){
wx_audio.audioPlay()
},document.getElementById("pause").onclick=function(){
wx_audio.audioPause()
},document.getElementById("cut").onclick=function(){
wx_audio.audioCut(music[1].src,music[1].title,music[1].descr)
}
进度条相关
源码里的进度条有好几个,先看看相关代码:
//实际播放进度条
this.wxVoiceP=document.createElement("span");
this.wxVoiceP.className="wx-voice-p";
this.wxAudioDetail.appendChild(this.wxVoiceP);
//缓冲进度条
this.wxBufferP=document.createElement("span");
this.wxBufferP.className="wx-buffer-p";
this.wxAudioDetail.appendChild(this.wxBufferP);
//进度条loading容器,
this.wxLoading=document.createElement("span");
this.wxLoading.className="wx-loading";
this.wxAudioDetail.appendChild(this.wxLoading);
//进度条上的loading效果
this.wxLoadingWrapper=document.createElement("span");
this.wxLoadingWrapper.className="wx-loading-wrapper";
this.wxLoading.appendChild(this.wxLoadingWrapper);
//进度条上的小圆点
this.wxAudioOrigin=document.createElement("div");
this.wxAudioOrigin.className="wx-audio-origin";
this.wxAudioP.appendChild(this.wxAudioOrigin);
wxVoiceP代表的是实际播放的进度条,它和wxAudioOrigin(小圆点)的进度是一致的。
wxBufferP代表的是缓冲进度条,它和播放进度不太一样,它一般会在当前播放点多缓冲一些。
wxLoading代表的是一个在进度条上的loading,如果出现等待的情况,会显示它。
Dom结构如下:
播放器上的事件
播放器上有很多事件,让我们一起来解读一下:
i.wxAudio.onplaying=function(){//播放
console.log('playing')
vart=newDate;
i.isPlaying=1;//设置播放标志
i.reduceTBefore=Date.parse(t)-Math.floor(1e3*i.wxAudio.currentTime);
console.log('reduceTBefore',newDate(i.reduceTBefore).format('YY-MM-DDHH:mm:ss'))
i.wxAudioStateImg.src=o//切换图片,变成播放的gif
}
播放音频的时候触发一次,上面reduceTBefore记录的是当前时间相对于当前播放时间的时间差,这个值比较有意思,如果音频一直流畅播放,那么这个值是不变的,因为当前时间在递增,当前播放时间也在递增。
i.wxAudio.onpause=function(){//暂停
i.isPlaying=0;
i.showLoading(0);
i.wxAudioStateImg.src=n;
}
暂停的时候,进度条关闭loading。
i.wxAudio.onloadedmetadata=function(){//资源加载完毕
console.log('onloadedmetadata')
i.durationT=i.wxAudio.duration;
i.wxAudioDuration.innerText=i.formartTime(i.wxAudio.duration);//de
}
资源加载完毕,显示音频的总时间durationT。
i.wxAudio.onwaiting=function(){
console.log('onwaiting')
if(i.wxAudio.paused==0){
i.showLoading(1)
}
}
当发生卡顿或者点击未播放过的进度条,会出发onwating,若此时正在播放,进度条会显示loading。
i.wxAudio.onprogress=function(){
console.log('process')
if(i.wxAudio.buffered.length>0){
for(vart=0,e=0;e
t+=i.wxAudio.buffered.end(e)-i.wxAudio.buffered.start(e);
if(t>i.durationT){
t=i.durationT;
i.showLoading(0);
}
}
varA=Math.floor(t/i.durationT*100);
i.wxBufferP.style.width=A+"%"
}
varo=newDate;
if(i.wxAudio.paused==0){
i.reduceTAfter=Date.parse(o)-Math.floor(1e3*i.currentT);
i.reduceTAfter-i.reduceTBefore>1e3?i.showLoading(1):i.showLoading(0)
console.log('reduceTAfter',newDate(i.reduceTAfter).format('YY-MM-DDHH:mm:ss'))
}
}
当音频发生下载的时候,会触发onprogress,将得到的buffered统计起来,更新缓冲进度条。
注意有一个reduceTAfter,它和reduceTBefore一样,也是得到当前时间相对于当前播放时间的一个值,reduceTAfter-reduceTBefore>1e3意思是当音频卡顿超过1s,就显示loading。
i.wxAudio.ontimeupdate=function(){
vart=newDate;
if(i.isDrag==0){
i.currentT=i.wxAudio.currentTime;
i.currentP=Number(i.wxAudio.currentTime/i.durationT*100);
i.reduceTBefore=Date.parse(t)-Math.floor(1e3*i.currentT);i.currentP=i.currentP>100?100:i.currentP;
i.wxVoiceP.style.width=i.currentP+"%";
i.wxAudioOrigin.style.left=i.currentP+"%";
i.wxAudioCurrent.innerText=i.formartTime(i.wxAudio.currentTime);
i.showLoading(0);
}
}
在声音一直在播放的时候,会一直触发ontimeupdate事件。会更新进度条额reduceTBefore。
i.wxAudioOrigin.onmousedown=function(t){
console.log('mousedown')
i.isDrag=1;
vare=(t||window.event).clientX,
A=t.target.offsetLeft;
i.maxProgressWidth=i.wxAudioDetail.offsetWidth;
i.wxAudioC.onmousemove=function(t){
if(i.isDrag){
varo=(t||window.event).clientX;
i.dragProgressTo=Math.min(i.maxProgressWidth,Math.max(0,A+(o-e)));
i.updatePorgress()
}
},i.wxAudioC.onmouseup=function(){
if(i.isDrag){
i.isDrag=0;
i.wxAudio.currentTime=Math.floor(i.dragProgressTo/i.maxProgressWidth*i.durationT)
}
},i.wxAudioC.onmouseleave=function(){
if(i.isDrag){
i.isDrag=0;
i.wxAudio.currentTime=Math.floor(i.dragProgressTo/i.maxProgressWidth*i.durationT)
}
}
}
i.wxAudioOrigin.ontouchstart=function(t){
console.log('touchstart')
i.isDrag=1;
vare=t||window.event,
A=e.touches[0].clientX,
o=e.target.offsetLeft;
i.maxProgressWidth=i.wxAudioDetail.offsetWidth;
i.wxAudioC.ontouchmove=function(t){
if(i.isDrag){
vare=(t||window.event).touches[0].clientX;
i.dragProgressTo=Math.min(i.maxProgressWidth,Math.max(0,o+(e-A)));
i.updatePorgress()
}
}
i.wxAudioC.ontouchend=function(){
if(i.isDrag){
i.isDrag=0;
i.wxAudio.currentTime=Math.floor(i.dragProgressTo/i.maxProgressWidth*i.durationT)
}
}
}
mousedown/mousemove/mouseup用来确定播放器的currentTIme;ontouchstart/ontouchmove/ontouchend是用来处理手机上的点击事件。