最近在学习微信小程序的UI组件,audio音频方面想做一个类似网易云的播放效果。基础需求:
1、能控制音频开始、暂停、停止
2、音乐播放,封面旋转,音乐暂停封面停止旋转
3、能显示歌曲的播放时间和进度条
4、能通过进度条控制音乐的播放进度
先上一张效果图
直接放代码,代码里面写了比较多的注释。
wxml:
<view class='item'>
<text>音乐播放器</text>
<image class='audio_post{{music_on?" music_on":""}}' style="animation-play-state:{{music_playing?'running':'paused'}}" src='http://y.gtimg.cn/music/photo_new/T002R300x300M000003rsKF44GyaSk.jpg?max_age=2592000' ></image>
<view class='audio_progress'>
<slider block-size='14' bindchange='audioChange' bindchanging='audioChanging' value='{{sliderValue}}'></slider>
<view>{{musicTime}}</view>
</view>
<view class='audio_control'>
<button type='primary' bindtap='playMusic'>播放</button>
<button type='primary' bindtap='pauseMusic'>暂停</button>
<button type='primary' bindtap='stopMusic'>停止</button>
</view>
</view>
wxss:
.item {
width: 100%;
padding-bottom: 30rpx;
display: flex;
flex-direction: column;
justify-content: center;
}
.item text {
font-size: medium;
}
.audio_progress{
width: 100%;
display: flex;
flex-direction: row;
justify-content: space-around;
}
.audio_progress slider{
width: 80%;
}
.audio_progress view{
padding: 18rpx;
}
.audio_post{
width: 300rpx;
height: 300rpx;
margin: 50rpx auto;
border-radius: 50%;
}
/* 旋转的样式 */
.music_on{
animation: audio-rotate 8s linear infinite;
}
.audio_control{
display: flex;
flex-direction: row;
justify-content:space-around;
}
.audio_control button{
width:200rpx;
height:80rpx;
line-height:80rpx;
}
/* 旋转动画 */
@keyframes audio-rotate {
0% {
transform: rotateZ(0deg);
}
100% {
transform: rotateZ(360deg);
}
}
js
//InnerAudioContext实例
var audioCxt;
//动画
var audioAnimation;
audioCxt = wx.createInnerAudioContext();
audioCxt.src = 'http://ws.stream.qqmusic.qq.com/M500001VfvsJ21xFqb.mp3?guid=ffffffff82def4af4b12b3cd9337d5e7&uin=346897220&vkey=6292F51E1E384E06DCBDC9AB7C49FD713D632D313AC4858BACB8DDD29067D3C601481D36E62053BF8DFEAF74C0A5CCFADD6471160CAF3E6A&fromtag=46';
Page({
/**
* 页面的初始数据
*/
data: {
audioAnimation : null,
//音乐是不是开始
music_on : true,
//音乐是不是在播放
music_playing :false,
//显示的时间
musicTime : '00:00',
sliderValue : 0
},
/**
* 生命周期函数--监听页面初次渲染完成
*/
onReady: function () {
//音乐播放结束触发
audioCxt.onEnded((res) =>{
//修改属性。去除css状态
this.data.music_on = false;
this.setData({
music_on: this.data.music_on
})
//重新播放
audioCxt.seek(0);
this.setData({
musicTime: '00:00',
sliderValue: 0
})
}),
//在播放状态,绑定播放进度更新事件。然后控制进度条和时间显示
audioCxt.onPlay((res) =>{
audioCxt.onTimeUpdate(this.timeUpdate)
})
},
//播放按钮事件
playMusic : function(){
this.data.music_on = true;
this.data.music_playing = true;
audioCxt.play();
//图片添加css样式,旋转样式
this.setData({
music_on: this.data.music_on,
music_playing: this.data.music_playing
})
},
//暂停按钮事件
pauseMusic : function(){
this.data.music_on = true;
this.data.music_playing = false;
audioCxt.pause();
this.setData({
music_on: this.data.music_on,
music_playing: this.data.music_playing
})
},
//停止按钮事件
stopMusic : function(){
audioCxt.stop();
this.data.music_on = false;
this.setData({
music_on: this.data.music_on
})
},
//进度条改变后触发事件
audioChange : function(e){
var length = audioCxt.duration;
var percent = e.detail.value;
//用进度条百分比 * 整个音乐长度
var musicTime = Math.round(length/100*percent);
audioCxt.seek(musicTime);
//因为在拖动进度条时,去除了时间绑定,所以进度改变后重新绑定
audioCxt.onTimeUpdate(this.timeUpdate);
this.setData({
musicTime: this.musicTimeFormat(musicTime)
})
},
//进度条拖动过程中触发事件
audioChanging : function(e){
//因为在进度条拖动的时候,还会在timeUpdate里面修改进度条的value,倒置拖动受影响,所以当拖动的时候需要取消绑定
audioCxt.offTimeUpdate();
//拖动时修改时间显示
var length = audioCxt.duration;
var percent = e.detail.value;
var musicTime = Math.round(length / 100 * percent);
this.setData({
musicTime: this.musicTimeFormat(musicTime)
})
},
//将秒钟转化为mm:ss的时间格式
musicTimeFormat : function(time){
var second = Math.floor(time % 60);
if(second<10){
second = '0' + second;
}
var minute = Math.floor(time / 60);
if (minute < 10) {
minute = '0' + minute;
}
return minute + ':' + second;
},
//播放的时候,更新进度条和时间显示
timeUpdate : function(){
var time = audioCxt.currentTime;
var percent = Math.round(time / audioCxt.duration * 100);
this.setData({
musicTime: this.musicTimeFormat(time),
sliderValue: percent
})
}
})
总结几个难点吧。
1、audio控件小程序已经不再更新了。都使用InnerAudioContext这个对象来控制音频。这个方法没有默认界面,需要自己写界面。
2、封面的旋转使用的css中的keyframes来进行的,用animation也尝试过,感觉比较复杂并且不好操作。用css来实现比较简单方便。
3、style="animation-play-state:{{music_playing?'running':'paused'}}" 这一个属性能控制动画暂停。有帖子说在IOS真机上会出现问题,没有苹果手机没进行测试。这个属性文档里面都没有找到。
4、进度条和播放的状态要进行双向绑定,播放的时候进度条的value要改变,进度条拖动的时候播放的时间也要进行改变。
5、自己有时候写变量还是不太规范。没形成自己的一套规则。
大家有什么疑问欢迎留言提问,多多交流。