微信小程序开发之——音乐播放器-播放器(3.4)

  • Post author:
  • Post category:小程序

一 概述

  • 常用组件及API介绍
  • 播放器页面任务
  • 播放器页面任务
  • 数据准备
  • 音乐播放功能
  • 播放器页面

二 常用组件及API介绍

2.1 音频API

介绍

  • 微信小程序提供了播放音频的API,掌握这个API的使用方法是实现音乐播放的关键。

  • 在使用音频API时,需要通过如下代码创建一个InnerAudioContext实例,audioCtx就是一个InnerAudioContext实例,也就是一个对象,利用这个对象的属性和方法可以完成具体的工作

    var audioCtx=wx.createInnerAudioContext()
    

常用属性和方法

类型 名称 说明
属性 src 音频资源的地址,用于直接播放
startTime 开始播放的位置(s),默认为0
autoplay 是否自动开始播放,默认为false
loop 是否循环播放,默认为false
volume 音量。范围0~1。默认为1
duration 音频的长度(s)。在当前有合法的src时返回(只读)
currentTime 音频的播放位置(s)。在当前有合法的src时返回(只读)
paused 当前是否暂停或停止状态(只读)
方法 play() 播放
pause() 暂停(暂停后的音频再播放会从暂停处开始播放)
stop() 停止(停止后的音频再播放会从头开始播放)
seek() 跳转到指定位置
destroy 销毁当前实例
onCanPlay() 音频进入可以播放状态的事件(参数为回调函数)
onPlay() 音频播放事件(参数为回调函数)
onPause() 音频暂停事件(参数为回调函数)
onStop() 音频停止事件(参数为回调函数)
onEnded() 音频自然播放至结束的事件(参数为回调函数)
onSeeked() 音频进行跳转操作的事件(参数为回调函数)
onTimeUpdate() 音频播放进度更新事件(参数为回调函数)
onError() 音频播放错误事件(参数为回调函数)

如何使用

onReady: function () {
    //创建InnerAudioContext实例
    var audioCtx=wx.createInnerAudioContext()
    //设置音频资源地址
    audioCtx.src='http://music.163.com/song/media/outer/url?id=5254524.mp3'
    //当开始播放时,输出调试信息
    audioCtx.onPlay(function(){
      console.log('开始播放')
    })
    //当发生错误时,输出信息
    audioCtx.onError(function(res){
      console.log(res.errMsg) //错误信息
      console.log(res.errCode) //错误码
    })
    //开始播放
    audioCtx.play()
  },

2.2 slider组件

说明

slider组件是小程序表单组件中的一种,用于滑动选择某一个值,在本项目中将用来实现播放器的进度条

常用属性

属性 类型 说明
min Number 最小值,默认为0
max Number 最大值,默认为100
step Number 步长,取值大于0,可被(max-min)整除,默认为1
value Number 当前取值,默认为0
activeColor Color 已选择的颜色,默认为#1aad19
backgroundColor Color 背景条的颜色,默认为#e9e9e9
block-size Number 滑块的大小,取值范围为12~28,默认为28
block-color Color 滑块的颜色,默认为#ffffff
show-value Boolean 是否显示当前value,默认为false
bindchange EventHandle 完成一次拖动后触发的事件
bindchanging EventHandle 拖动过程中触发的事件

基本使用

布局文件中:

<slider bindchanging="sliderChanging" show-value />

代码中:

sliderChanging:function(e)
{
   console.log(e.detail.value)
}

三 播放器页面任务

  • 音乐信息:显示当前播放曲目的标题和艺术家
  • 专家封面:当音乐播放时,专辑封面会顺时针旋转
  • 播放进度:显示当前曲目的播放时长和总时长,并提供一个进度条,当音乐播放时进度条就会增长,用户也可以手动改变进度条的进度来跳转播放进度

四 数据准备

4.1 音乐外链平台

刘志进实验室-音乐直链搜索

4.2 定义基础数据

路径

pages/index/index.js文件的data对象定义基础数据playlist

数据

data: {
    item:0,
    tab:0,
    playlist:[{
      id:1,title:'钢琴协奏曲',singer:'肖邦',
      src:'http://music.163.com/song/media/outer/url?id=419485661.mp3',
      coverImgUrl:'../../images/music.png'
    },{
      id:2,title:'奏鸣曲',singer:'莫扎特',
      src:'http://music.163.com/song/media/outer/url?id=1394618521.mp3',
      coverImgUrl:'../../images/music.png'
    },{
      id:3,title:'欢乐颂',singer:'贝多芬',
      src:'http://music.163.com/song/media/outer/url?id=383064.mp3',
      coverImgUrl:'../../images/music.png'
    },{
      id:4,title:'爱之梦',singer:'李斯特',
      src:'http://music.163.com/song/media/outer/url?id=5276814.mp3',
      coverImgUrl:'../../images/music.png'
    },
    ],
    state:'paused',
    playIndex:0,
    play:{
      currentTime:'00:00',
      duration:'00:00',
      percent:0,
      title:'',
      singer:'',
      coverImgUrl:'../../images/music.png'
    }
  },

playlist数据说明

  • id:每条记录的唯一标识
  • title:曲目标题
  • singer:艺术家
  • src:网络中的音频文件链接地址
  • coverImgUrl:专辑封面图片的链接地址

音乐状态属性

  • state:音乐的播放状态,paused表示暂停,running表示播放
  • playIndex:当前播放曲目在播放列表数组中的索引值
  • play:当前播放曲目的信息
  • currentTime:播放时长
  • duration:总时长
  • percent:播放进度
  • title:当前播放的曲目标题
  • singer:当前播放的曲目的艺术家
  • coverImgUrl:当前播放的曲目的专辑封面

五 音乐播放功能(底部播放器)

5.1 布局文件(pages/index/index.wxml)

<view class="player">
  <image class="player-cover" src="{{play.coverImgUrl}}" />
  <view class="player-info">
    <view class="player-info-title">{{play.title}}</view>
    <view class="player-info-singer">{{play.singer}}</view>
  </view>
  <view class="player-controls">
    <!--切换到播放列表-->
    <image src="../images/list.png" bindtap="changePage" data-page="2" />
    <!--播放-->
    <image wx:if="{{state=='paused'}}" src="../images/Play.png" bindtap="play"/>
    <image wx:else src="../images/Pause.png" bindtap="pause"/>
     <!--下一曲-->
     <image src="../images/rewind-right.png" bindtap="next"/>
</view>

5.2 样式文件(pages/index/index.wxss)

.player{
  display: flex;
  align-items: center;
  background: #222;
  border-top: 1px solid #252525;
  height: 112rpx;
}
.player-cover{
  width: 80rpx;
  height: 80rpx;
  margin-left: 15rpx;
  border-radius: 8rpx;
  border:1px solid #333;
}
.player-info{
  flex:1;
  font-size: 10pt;
  line-height: 38rpx;
  margin-left: 20rpx;
  padding-bottom: 8rpx;

}
.player-info-singer{
  color: #888;

}
.player-controls image{
  width:80rpx;
  height: 80rpx;
  margin-right: 15rpx;
}

5.3 逻辑文件(pages/index/index.js)

audioCtx:null,
onReady: function () {
    this.audioCtx=wx.createInnerAudioContext()
    //默认选中第1曲
    this.setMusic(0)
 },
setMusic:function(index){
    var music=this.data.playlist[index]
    this.audioCtx.src=music.src
    this.setData({
      playIndex:index,
      'play.title':music.title,
      'play.singer':music.singer,
      'play.coverImgUrl':music.coverImgUrl,
      'play.currentTime':'00:00',
      'play.duration':'00:00',
      'play.percent':0
    })
  }, 
  play:function(){
    this.audioCtx.play()
    this.setData({state:'running'})
  },
  pause:function(){
    this.audioCtx.pause()
    this.setData({state:'paused'})
  },
  next:function(){
    var index=this.data.playlist>=this.data.playlist.length-1?0:this.data.playIndex+1
    this.setMusic(index)
    if(this.data.state=='running'){
      this.play()
    }
 }, 

5.4 效果

六 播放器页面

6.1 布局文件(pages/index/play.wxml)

<view class="content-play">
<!--显示音乐信息-->
<view class="content-play-info">
  <text>{{play.title}}</text>
  <view>——{{play.singer}}——</view>
</view>
<!--显示专辑封面-->
<view class="content-play-cover">
  <image src="{{play.coverImgUrl}}" style="animation-play-state:{{state}}"/>
</view>
<!--显示播放进度和时间-->
<view class="content-play-progress">
  <text>{{play.currentTime}}</text>
  <view>
    <slider bindchange="sliderChange" activeColor="#d33a31" block-size="12" bindchange="#dadada" value="{{play.percent}}" />
  </view>
  <text>{{play.duration}}</text>
</view>
</view>

6.2 样式文件(pages/index/index.wxss)

.content-play{
  display: flex;
  justify-content: space-around;
  flex-direction: column;
  height: 100%;
  text-align: center;
}
.content-play-info>view{
  color: #888;
  font-size: 11pt;
}
.content-play-cover image{
  animation:rotateImage 10s linear infinite;
  width: 400rpx;
  height: 400rpx;
  border-radius: 50%;
  border: 1px solid #333;
}
@keyframes rotateImage{
  from {
    transform:rotate(0deg);
  }
  to {
    transform:rotate(360deg);
  }
}
.content-play-progress{
  display: flex;
  align-items: center;
  margin:0 35rpx;
  font-size:9pt;
  text-align: center;
}
.content-play-progress>view{
  flex:1;
}

6.3 逻辑文件(播放进度)

 onReady: function () {
 this.audioCtx=wx.createInnerAudioContext()
 var that=this;
 //播放失败检测
 this.audioCtx.onError(function(){
  console.log('播放失败:'+that.audioCtx.src)
 })
 //播放完成自动换下一曲
 this.audioCtx.onEnded(function(){
   that.next()
  })
  //自动更新播放进度
  this.audioCtx.onPlay(function(){ })
  this.audioCtx.onTimeUpdate(function(){
  that.setData({
      'play.duration': formatTime(that.audioCtx.duration),
      'play.currentTime': formatTime(that.audioCtx.currentTime),
      'play.percent': that.audioCtx.currentTime/that.audioCtx.duration*100
      })
  })
  //默认选择第1曲
  this.setMusic(0)
  //格式化时间
  function formatTime(time){
    var minute=Math.floor(time/60)%60;
    var second=Math.floor(time)%60
    return (minute<10?'0'+minute:minute)+':'+(second<10?'0'+second:second)
    }
  },
  
 sliderChange:function(e){
   var second=e.detail.value*this.audioCtx.duration/100
   this.audioCtx.seek(second)
  },  

6.4 效果图


版权声明:本文为Calvin_zhou原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。