深蓝互联专注深圳物联网方案开发定制、小程序开发、SaaS系统、APP开发和深圳软硬件方案公司欢迎咨询邮箱:wisepu@szdbi.com   电话:13530005652   联系我们   |   网站地图   



微信小程序音乐播放器

来源:     发布:     点击:

 小程序有两个页面,主页与播放页,因为采用了leanCloud作为后台数据开发,所以有一个lib包

  树结构,上图 附微信小程序使用leanCloud链接

  index页的功能描述:提供音乐查找与选择,搜索框不输入点击搜索得到数据库中所以音乐文件(.mp3格式),支持对歌名或歌手的模糊查询;

点击列表中的某一首即可跳转至播放页进行播放,从播放页清单回退至index页时,index页底部有播放小窗,点击可回到播放页

  看这里:

  

 

  代码送上:index.wxml

复制代码
<view class='theMain' style='background-image:url({{bgimage}});'>
<view>
  <image class='image1'src="{{imageUrl}}" mode='aspectFit' wx:if="{{!searchTop}}">
  </image>
</view>
<view class='page_row'>  
      <view class="search">  
        <view class="df search_arr">  
          <icon class="searchcion" size='20' type='search'></icon>  
          <input class="searchInput" placeholder="请输入歌名,歌手" value="{{searchValue}}" bindinput='searchValueInput'/>  
        </view>  
      </view>  
      <view class='sousuo' bindtap='sousuoButton'>搜索</view>  
</view> 
<view class='listBar'>
  <text class="search_top" style='width:80%;' wx:if="{{searchTop}}">搜索结果</text>
</view>
<view wx:for='{{json}}' class='music_list' bindtap='playTheMusic'data-name="{{item.name}}" data-url="{{item.url}}">
  <text class='musictext'>{{item.name}}</text>
  <view class='url'>{{item.url}}</view>
</view>

<view class="search_no" wx:if="{{!centent_Show}}">
  <text>暂时没有库存,联系冯大神上传哈</text>
</view>
<view class='littlebar' bindtap='littlebar'>
  <view class='littleImage' style='background-image:url({{imageUrl}});'></view>
  <view class='littleName'>
  <text class='songNameText'>{{songName}}</text>
  </view>
</view>
</view>
复制代码

 

  index.wxss这个css样式代码我觉得就没啥可看的啦,这个还是看自己喜好调,如果需要的话,文章最下方附有Github链接,

重要的还是在index.js上啦,一起来看看(我觉得不错的地方直接在代码上标注了,可以参考一下)

复制代码
const AV = require("../../libs/av-weapp-min");//这里是对LeanCloud的引用,大家需要的话可问度娘,很多详细教程,我还是蛮喜欢这个工具的
var app=getApp()
Page({


  /**
   * 页面的初始数据
   */
  data: {
    imageUrl: "http://lc-9qxpppvr.cn-n1.lcfile.com/9c1af72ea0506789a9b9.jpg",
    searchValue:'',      //搜索值
    centent_Show: true,    //这个可看wxml中的wx:if属性,用来动态显示与隐藏
    searchTop:false,       //同上
    bgimage: '',           //背景图片,在得到搜索结果的时候显示
    toName:'',
    songName:''
  },

  searchValueInput: function (e) {//得到搜索框的内容并渲染到data下的searchValue中
    var value = e.detail.value;
    this.setData({
      searchValue: value,
    });
  },

  sousuoButton:function(){//对LeanCloud数据库的查询操作

      var that=this;       //这里非常重要,注意,此函数中then方法内还有一个函数,而该函数需要用到setData渲染数据。经过两层不可以直接用this.setData
      var nameQuery1 = new AV.Query('_File');
      nameQuery1.contains('name', that.data.searchValue);
      var nameQuery2 = new AV.Query('_File');
      nameQuery2.contains('name', '.mp3');
      var query = new AV.Query.and(nameQuery1, nameQuery2);//这里相当于数据库where语句下的and操作
      query.find().then(function (results) {
        // results is an array of AV.Object.
        //将data转成json格式
        //转为数组
        var jsonObj = JSON.parse(JSON.stringify(results));
        app.globalData.musicList=jsonObj.concat(); //设置了全局变量,concat()方法为数组的复制,playing页面需要。具体用法可问度娘,app对象为顶部创建的对象
        if (jsonObj.length == 0) {
          that.setData({
            centent_Show: false,
          });
          return;
        }
          that.setData({
            json: app.globalData.musicList,
            searchTop:true,
            bgimage: "http://lc-9qxpppvr.cn-n1.lcfile.com/9c1af72ea0506789a9b9.jpg",
            centent_Show:true
          });
          console.log(that.data.c)
      }, function (error) {
        console.log(error);
        // error is an instance of AVError.
      });
  },
  //点击底部音乐bar进入play界面
  littlebar: function () {  //这里有一个较难解决的问题,我会在下面单独写出,大神要是有思路请赐教,毕竟我才入门4天,很多都不懂
    var pages=getCurrentPages();
    var playingPage=pages[pages.length-2];
    playingPage.setData({
      angle:app.globalData.angle,
    })
    wx.navigateBack();
  },
  //点击清单跳转到播放界面
  //data-name="{{item.name}}" data-url="{{item.url}}"
//只有在列表渲染的view控件中设置这些属性,该函数才可得到点击后对应的属性(可见上面的index.wxml)

  playTheMusic:function(e){
    console.log(e.currentTarget.dataset.name);  //一个调试方法,调试器输出点击的歌曲名
    this.setData({
      toName: e.currentTarget.dataset.name
    });
    var songUrl = e.currentTarget.dataset.url;
    var songName = e.currentTarget.dataset.name;
    app.globalData.songName = songName;
    var theUrl = "../playing/playing?songUrl=" + songUrl + "&songName=" + songName //url携带参数
    wx.redirectTo({  //此种跳转当前页面数据会保存在页面栈中,可以回退,可问度娘      
    url: theUrl,
  })
  },

  /**
   * 生命周期函数--监听页面加载
   */
  onLoad: function (options) {
    /** 
     * 监听音乐播放 
     */
    wx.onBackgroundAudioPlay(function () {
      // callback
      console.log('onBackgroundAudioPlay')
    })
  },
/**
   * 生命周期函数--监听页面显示
   */
  onShow: functionthis.setData({
      songName: app.globalData.songName ,
      json: app.globalData.musicList,
      searchTop: true,
    }); 
  }
})
复制代码

  好了,这里我想谈一下在index.js中我提到的单独讲的内容。情景在于微信小程序界面之间的跳转,使用wx.navigateTo()方法跳转到另一个页面时可以将当前页面存入页面栈,再通过wx.navigateBack()方法对页面栈出栈操作,可回退到当前页面,使用wx.redirectTo()直接跳转,不存入页面栈。在这个程序中,index->playing->index->playing重复多次无法直接实现。这个问题我想了很久还是没有完美的将其解决。

  我的暂时逻辑是:点击对应音乐使用wx.redirectTo()方法,不保存页面栈,跳转至playing页;在playing页点击list图标使用wx.navigateTo(),保存页面栈,同时跳到index页,这时候会调用onShow()函数,将保存的list信息渲染到index页面上;点击index底部的播放小框调用wx.navigateBack()方法回到playing页(playing页的数据较多,所以采用了这种逻辑)

  哪位大哥有更好解决方法烦请赐教哈

  接下来是playing页:(推荐使用wx.getBackgroundAudioManager()接口对音乐行为进行操作

  此页面需要完成播放、暂停、上一曲、下一曲、回到index页、动态显示播放时间和总长度(部分实现)、快进(还未实现)

  看界面:

  

  然后上代码了:
  playing.wxml:图标来源于百度图片,简单ps抠图后传至云端使用;中间专辑图旋转感谢这篇博客,其中的旋转快慢,每次角度可通过调节常量值实现,下面代码有标注

复制代码
<view class='Main'>
  <view class='songNameView'>
    <text></text>
    <text class='songName'>{{name}}</text>
  </view>
  <view class='imageView' style="background-image: url({{imageUrl}});" animation="{{animationData}}">
  </view>
   <view class="backIndex" bindtap='backIndex' style='background-image:url({{homeImage}})'></view>
  <view class='line'>
    <view class='nowView'>
      <text class='now'>{{cur}}</text>
    </view>
    <view class='theLine'></view>
    <view class='allTimeView'>
      <text class='allTime'>{{duration}}</text>
    </view>
  </view>
  <view class="button">
    <view class='back MusicIcon' style="background-image: url({{backUrl}});" bindtap='theBack'></view>
    <view class='center MusicIcon' style="background-image: url({{playOrStopUrl}});" bindtap='play'></view>
    <view class='next MusicIcon' style="background-image: url({{nextUrl}});" bindtap='theNext'></view>
  </view>
</view>
复制代码

同样,playing.wxss可在我的Github中查看

下面是展示playing.js的时刻,各种逻辑在代码中直接标注了

复制代码
// pages/playing/playing.js
const AV = require("../../libs/av-weapp-min");
var app = getApp()
Page({

  /**
   * 页面的初始数据
   */
  data: {
    name:'测试',
    url:'',
    imageUrl:'http://lc-9qxpppvr.cn-n1.lcfile.com/9c1af72ea0506789a9b9.jpg',
    homeImage:"http://lc-9qxpppvr.cn-n1.lcfile.com/a9603240aab63a7950b0.png",
    animationData: {},
    isPlay:false,   //播放标志
    thePosition:0,  //用来保存暂停时播放位置
    angle:0,        //用来不断保存旋转次数,用于解决界面多次跳转后旋转失速问题
    cur:'--:--',    //当前时间
    duration:'--:--'  //总时长
  
  },
  //返回到清单页

//此处在上面有提及,点击list图标到index页面,并将跳转前最后一个旋转角度渲染给全局变量
  backIndex: function () {
    wx.navigateTo({
      url: '../index/index',
    });
    app.globalData.angle=this.data.angle;
  },

  /**
   * 生命周期函数--监听页面加载
   */
  onLoad: function (options) {
    //加载传递过来的参数
  //options为随url传递过来的参数

    this.setData({
      name: options.songName,
      url: options.songUrl,
      imageUrl:"http://lc-9qxpppvr.cn-n1.lcfile.com/9c1af72ea0506789a9b9.jpg",
      backUrl:"http://lc-9qxpppvr.cn-n1.lcfile.com/2574f1888750f8eaea88.png",
      nextUrl:"http://lc-9qxpppvr.cn-n1.lcfile.com/299a6353324cb312b00e.png",
      playOrStopUrl:"http://lc-9qxpppvr.cn-n1.lcfile.com/56885a2b7b3e478dd0c6.png",
      isPlay:true
    })
    //加载页面时执行播放动作
    wx.playBackgroundAudio({
      dataUrl: this.data.url,
    })
  },
  //播放/暂停
  play:function(){
    const backgroundAudioManager = wx.getBackgroundAudioManager();
    var theTime;
    var allTime;
    if(this.data.isPlay){
      wx.pauseBackgroundAudio();  //推荐都使用这个API,我之前不知道这个API,导致在后来的开发中无法实现上面列举的全部功能
      theTime = backgroundAudioManager.currentTime;//不甘心,所以在点击播放或暂停时可对页面进行时间的动态渲染,也算是完成了一点吧
      allTime = backgroundAudioManager.duration; 
      var theString1 = theTime.toFixed(0);
      var theInt1 = parseInt(theString1);
      var m1 = theInt1 / 60;
      var mString1 = m1.toFixed(0); //截取小数点后0位数字,结果为String类型
      var mInt1 = parseInt(mString1); //转number
      var s1 = theInt1 % 60 / 100;
      var cur = mInt1 + s1;
      var theString = allTime.toFixed(0);
      var theInt = parseInt(theString);
      var m = theInt/60;
      var mString = m.toFixed(0);
      var mInt = parseInt(mString);
      var s = theInt%60/100;
      var all = mInt+s;
      this.setData({
        playOrStopUrl:"http://lc-9qxpppvr.cn-n1.lcfile.com/22a26757fca8c46a2940.png",//替换为暂停图标
        isPlay: false,   //渲染一些需要的数据
        thePosition: theTime,
        duration:all,
        cur: cur
      });
    }else{
      backgroundAudioManager.seek(this.data.thePosition);
      backgroundAudioManager.play();
      this.setData({
        playOrStopUrl: "http://lc-9qxpppvr.cn-n1.lcfile.com/56885a2b7b3e478dd0c6.png",
        isPlay:true
      });
    }
  },

  //下一首
  theNext:function(){//对全局变量下的查找清单进行操作,如果当前歌曲为最后一首,跳转到第一首
    var j;
    var musicList = getApp().globalData.musicList.concat();
    for (var i = 0; i < musicList.length;i++){
      if(musicList[i].name==this.data.name){
        j=i;
        break;
      }else{
        j=-1;
      }
    }
    if (musicList.length-1==j){
      this.setData({
        name: musicList[0].name,
        url: musicList[0].url
      });
    }else{
      this.setData({
        name: musicList[j+1].name,
        url: musicList[j + 1].url
      });
    }
      wx.playBackgroundAudio({
        dataUrl: this.data.url,
      })
  },

  //上一首
  theBack:function(){//若为第一首,跳转到最后一首
    var j;
    var theLength=0;
    var musicList = getApp().globalData.musicList.concat();
    theLength=musicList.length;
    for (var i = 0; i < musicList.length; i++) {
      if (musicList[i].name == this.data.name) {
        j = i;
        break;
      } else {
        j = 1;
      }
    }
    if (j==0) {
      this.setData({
        name: musicList[theLength-1].name,
        url: musicList[theLength-1].url
      });
    } else {
      this.setData({
        name: musicList[j-1].name,
        url: musicList[j-1].url
      });
    }
    wx.playBackgroundAudio({
      dataUrl: this.data.url,
    })
  },/**
   * 生命周期函数--监听页面显示
   */
  onShow: function () {//这里为专辑图旋转函数,调用wx.createAnimation()接口,更多参数详情可看官方API
    var animation = wx.createAnimation({
      duration: 1000,
      timingFunction: 'ease',
    })

    this.animation = animation

    // animation.scale(2, 2).rotate(45).step()

    this.setData({
      animationData: animation.export()
    })
    var n = 0;
    //连续动画需要添加定时器,所传参数每次+1就行
    setInterval(function () {
      n=this.data.angle;
      if(this.data.isPlay){//暂停时停止旋转,播放旋转的逻辑
        n = n + 1;  
      }else{
        n=n;
      }
      this.setData({
        angle: n,
      })  
      this.animation.rotate(8 * n).step()//8为每次转8°,应该是,个人喜好设置
      this.setData({
        animationData: this.animation.export()
      })
    }.bind(this), 360)//360ms转一个角度,个人喜好设置
  }
})
复制代码

  OK,到这里就可以实现一个演示视频中所有功能的简易播放器了,是不是觉得很简单。

深蓝互联成立于2013年,是一家物联网硬件开发及软件应用服务商,获得多次获得国家高新技术企业资质的企业。深蓝互联专注软硬件技术开发的专业性技术公司。我们从事软硬件开发十年,擅长SaaS 平台开发、APP小程序开发、软硬件结合开发,在视觉识别处理、数据架构、云计算、多线程高并发和集群、数据安全加密和防护方便有很深的技术积累。

 

我们拥有专业优秀的设计和技术团队,以极具创意的 UI 设计、精湛卓越的开发技术,专业的网络策划团队。公司多年来投入打造物联网SaaS平台,集成了公司研发的多款智能物联网终端(智能鲜米机、生鲜售货机、自助洗车机、小区电瓶车充电系统等)。

 

公司一直坚持以研发为导向,打造软硬件结合的物联网平台系统。将一直坚持提高开发的技术实力更好的为我们的客户服务!

 

文章来自深蓝互联http://www.szdbi.com/WEBkaifajishu/370.html转载请注明出处!

相关文章

无相关信息


深圳市龙华新区龙观西路2号宝龙大厦A903(与布龙路交汇处)