微信小程序播放器的一些简单功能实现

172 阅读4分钟

该内容只涉及静态页面以及静态的播放列表(如若使用接口,可自行修改)

准备工作

一、构建npm(后面用到moment的格式化时间)

image.png

二、系统后台监测程序播放器配置(系统后台要知道该播放器是否在播放歌曲,并有一些简单的业务逻辑)

在app.json中添加以下代码----和tarbar同级

"requireBackgroundModes": [
    "audio"
  ]

三、由于后面用到后台需要监测是哪首歌,需要有id和播放状态

在app.js中添加如下代码-----和onLaunch同级

GroupData:{
    MusicId:'',
    MusicPlay:false
  },

开始工作

涉及的功能介绍

1.单曲循环功能

2.上一首

3.下一首

4.播放

5.列表展示

6.进度条实时

image.png

由于本人比较懒,逐个功能介绍较复杂,直接附送源码,如看代码不明白,可直接联系本人

js部分


const appInstance = getApp()
Page({

  /**
   * 页面的初始数据
   */

  data: {
    isXunhuan:false,//是否开启循环
    isPlay:false, //是否正在播放
    isShow:false,  //是否展示列表
    currentTimeFomat:'0:00', //当前的时间---格式化后
    currentTime:'0', //当前时间
    durationTime:'', //总时间
    currentWidth:0 , //进度条宽度

    currentId:'001',  //当前播放歌曲id
    currentUrl:'http://music.163.com/song/media/outer/url?id=317151.mp3',  //当前播放歌曲地址
    currentTitle:'第一首',  //当前播放歌曲名称
    musicList:[{            //播放列表
      id:"001",
      url:'http://music.163.com/song/media/outer/url?id=317151.mp3',
      title:'第一首'
    },{
      id:"002",
      url:'http://downsc.chinaz.net/Files/DownLoad/sound1/201906/11582.mp3',
      title:'第二首'
    },{
      id:"003",
      url:'http://music.163.com/song/media/outer/url?id=298317.mp3',
      title:'第三首'
    }]
  },
  //点击列表按钮---展示列表页
  showList(){
    this.setData({
      isShow:true
    })
  },
  //点击别处--关闭列表页
  colseList(){
    if(this.data.isShow){
      this.setData({
        isShow:false
      })
    }
  },
  //点击列表里面的歌获得当前的歌曲
  musicListChange(e){
    this.setData({
      currentId:e.currentTarget.dataset.id,
      currentUrl:e.currentTarget.dataset.url,
      currentTitle:e.currentTarget.dataset.title,
    })
    this.musicControl(true)
  },
  //点击播放按钮
  bofang(){
    let isPlay = !this.data.isPlay  //修改播放状态
    this.musicControl(isPlay)  //传递的是已经修改了状态
  },
  //播放函数
  musicControl(isPlay){
    console.log(isPlay)
    if(isPlay){
      this.BackgroundAudioManager.src=this.data.currentUrl,
      this.BackgroundAudioManager.title=this.data.currentTitle
    }else{
      this.BackgroundAudioManager.pause()
    }
  },
  xunhuan(){
    console.log("已经开启循环播放")
    this.setData({
      isXunhuan:true
    })
  },
  xiayishou(){
    const {musicList}=this.data
    let url=''
    let title=''
    let id=''
    for(let i=0;i<musicList.length;i++){
      if(this.data.currentId==musicList[i].id){
        url=musicList[i+1].url
        id=musicList[i+1].id
        title=musicList[i+1].title
     
      }
    }
    console.log(url,id,title)
    this.setData({
      currentTitle:title,
      currentUrl:url,
      currentId :id
    })
    this.musicControl(true)
   
  },
  xunhuan2(){
    const {musicList}=this.data
    let url=''
    let title=''
    let id=''
    for(let i=musicList.length-1;i>=0;i--){
      if(musicList[i].id==this.data.currentId){
        console.log(musicList[i].id)
        url=musicList[i].url
        id=musicList[i].id
        title=musicList[i].title
      }
    }
    this.setData({
      currentUrl:url,
      currentId:id,
      currentTitle:title
    })
    this.musicControl(true)

  },
  shangyishou(){
    const {musicList}=this.data
    let url=''
    let title=''
    let id=''
    for(let i=musicList.length-1;i>=0;i--){
      if(musicList[i].id==this.data.currentId){
        console.log(musicList[i].id)
        url=musicList[i-1].url
        id=musicList[i-1].id
        title=musicList[i-1].title
      }
    }
    this.setData({
      currentUrl:url,
      currentId:id,
      currentTitle:title
    })
    this.musicControl(true)

  },
  /**
   * 生命周期函数--监听页面加载
   */
  onLoad(options) {
    this.BackgroundAudioManager =wx.getBackgroundAudioManager()
    
    // this.BackgroundAudioManager.src=this.data.currentUrl,
    // this.BackgroundAudioManager.title=this.data.currentTitle
    // this.BackgroundAudioManager.play()
    const MusicId=this.data.currentId
    console.log(appInstance.GroupData)
    //判断当前页面音乐是否在播放
    if (appInstance.GroupData.MusicPlay && appInstance.GroupData.MusicId === MusicId) {
      //修改当前音乐播放状态为true
      this.setData({
        isPlay: true
      })
    }
    this.BackgroundAudioManager.onPlay(() => {
      this.setData({
        isPlay: true
      })
      appInstance.GroupData.MusicPlay = true
      appInstance.GroupData.MusicId = MusicId
    })
    this.BackgroundAudioManager.onPause(() => {
      this.setData({
        isPlay: false
      })
      appInstance.GroupData.MusicPlay = false
      //由于上面必定是先播放后停止所以省略 appIstance.GroupData.MusicPlay=false
    })
    this.BackgroundAudioManager.onStop(() => {
      this.setData({
        isPlay: false
      })
      appInstance.GroupData.MusicPlay = false
    })
    this.BackgroundAudioManager.onTimeUpdate(()=>{
      let currentTimeFomat=moment(this.BackgroundAudioManager.currentTime*1000).format('mm:ss')
      //  console.log(this.BackgroundAudioManager.currentTime)
      //  console.log(this.BackgroundAudioManager.duration)

      let durationTime=Math.floor(this.BackgroundAudioManager.duration)
      let currentWidth=this.BackgroundAudioManager.currentTime/this.BackgroundAudioManager.duration*450

     if(Math.floor(this.BackgroundAudioManager.duration)==Math.ceil(this.BackgroundAudioManager.currentTime)){
       if(this.data.isXunhuan==false){
        console.log("下一首了")
        this.xiayishou()
       }else{
         console.log("因为开启了循环")
        this.xunhuan2()
       }
      
      }
      this.setData({
        currentTimeFomat,
        currentTime:Math.ceil(this.BackgroundAudioManager.currentTime),
        currentWidth,
        durationTime
      })
    });
    this.BackgroundAudioManager.onEnded(()=>{
      //进度条置为0
      this.setData({
        currentWidth:0,
        currentTime:'0'
      })
    });
  },

  /**
   * 生命周期函数--监听页面初次渲染完成
   */
  onReady() {

  },

  /**
   * 生命周期函数--监听页面显示
   */
  onShow() {

  },

  /**
   * 生命周期函数--监听页面隐藏
   */
  onHide() {

  },

  /**
   * 生命周期函数--监听页面卸载
   */
  onUnload() {

  },

  /**
   * 页面相关事件处理函数--监听用户下拉动作
   */
  onPullDownRefresh() {

  },

  /**
   * 页面上拉触底事件的处理函数
   */
  onReachBottom() {

  },

  /**
   * 用户点击右上角分享
   */
  onShareAppMessage() {

  }
})

html部分

<view class="container" >
  <text class="musicName" bindtap="colseList">{{currentTitle}}</text>
  <view class="circle">
    <image src="../../image/disc.png" alt="" class="disc"></image>
    <image src="../../image/needle.png"
    class="needle"></image>  
    <image src="../../image/nvsheng.jpg"
    class="nvsheng"></image>
  </view>
  <view class="progressbar">
    <text>0:00</text>
    <view class="barprogress">
      <view class="barprogress-timely" style="width:{{currentWidth+'rpx'}}"> 
        <view class="barcircle">
        </view>
      </view>
    </view>
    <text>{{currentTimeFomat}}</text>
  </view>

  <view class="controls">
   <view class="musicControls">
    <text class="iconfont icon-xunhuanbofang" bindtap="xunhuan"></text>
    <text class="iconfont icon-shangyishou" bindtap="shangyishou"></text>
    <text class="iconfont {{isPlay?'icon-zanting':'icon-bofang'}}" bindtap="bofang"></text>
    <text class="iconfont icon-xiayishou" bindtap="xiayishou"></text>
    <text class="iconfont icon-liebiao" bindtap="showList" hover-stop-propagation="true"></text>
   
  </view>
  <view class="songList" wx:if="{{isShow}}">
      <view class="songItem" wx:for="{{musicList}}" data-url="{{item.url}}" data-id="{{item.id}}" data-title="{{item.title}}" bindtap="musicListChange">{{item.id}}--{{item.title}}</view>
    </view>
   </view> 
</view>

css部分

.container{
  padding:20rpx;
  background-color: rgba(0,0,0,0.5);
  text-align: center;
  height:100%;
}
.musicName{
  color: white;
}
.circle{
  
  position: relative;
  margin-top:40rpx;
 
}
.disc{
  position: relative;
  z-index:1;
  height:598rpx;
  width:598rpx;
}
.needle{
  position:absolute;
  left:350rpx;
  top:-20rpx;
  height:200rpx;
  width:200rpx;
  z-index:999
}
.nvsheng{
  height:370rpx;
  width:370rpx;
  position: relative;
  top:-498rpx;
  left:0rpx;
  z-index: -999;
}
/* 包裹进度条 */
.progressbar{
  position: absolute;
  bottom: 200rpx;
  height:80rpx;
  width:640rpx;
  line-height: 80rpx;
  display: flex;
}
.barprogress{
  position: relative;
  height:4rpx;
  width:450rpx;
  background: rgba(0,0,0,0.5);
  margin:auto
}
/* 真实进度条 */
.barprogress-timely{
  position: absolute;
  top:0;
  left:0;
  z-index: 1;
  height:4rpx;
  background-color: red;
} 
/* 小圆球 */
.barcircle{
  position: absolute;
  top:-4rpx;
  right:-12rpx;
  height:12rpx;
  width:12rpx;
  border-radius: 50%;
  background-color: #fff;
}

.musicControls{
  display: flex;
  height:100rpx;
  line-height: 100rpx;
  margin-top:-30rpx;
}
.musicControls text{
  width:20%;
 font-size: 50rpx;
}
.musicControls text:nth-child(3)
{
  font-size: 65rpx;
}
.songList{
  position:fixed;
  top:400rpx;
  right:20rpx;
  width: 94%;
  background-image: linear-gradient(120deg, #f093fb 0%, #f5576c 100%);
  border-radius: 20rpx;
  z-index: 10000;
  height:calc(100vh - 400rpx)
}
.songItem{
    height:100rpx;
    line-height: 100rpx;
    color: white;

}

内附三张图片------右键可直接拿走

disc.png needle.png nvsheng.jpg

播放器字体图标的引入------这边就不放出来了

有需要的可以自行到阿里图标库下载相关字体 [[iconfont-阿里巴巴矢量图标库](www.iconfont.cn