微信小程序音樂播放器


寫在前面

  1.入門幾天小白的作品,希望為您有幫助,有好的意見或簡易煩請賜教

  2.微信小程序審核音樂類別已經下架,想要發布選題需慎重。附一個參考鏈接,感謝https://www.hishop.com.cn/xiaocx/show_53774.html

  3.寫的過程中參考了前輩們的方法,借過幾位博客園、CSDN、簡書前輩的路,這里表示感謝。

  4.官方API很重要

寫在第二

  資深大牛在地鐵上問我有沒有玩過微信小程序,自覺慚愧。於是萌發了寫個小程序長長見識的想法,畢竟,誰都想要做一位行業大牛嘛。

寫這個小程序花了4天,中間第一天無從下手,第二天開悟,到后兩天的優化。這中間我收獲極大,感謝生活。OK,廢話不多說。進入正文

正文在這里

  先看效果吧 求求你點開我吧

  小程序有兩個頁面,主頁與播放頁,因為采用了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,到這里就可以實現一個演示視頻中所有功能的簡易播放器了,是不是覺得很簡單。

  相對於網上很多前輩的功能完善的音樂播放器來說,我這個真的是望塵莫及,未來還有很長的路要走。但是東西出來了嘛, 還是很開心的;當然,我還是會不斷的去完善它的,這之中的playing頁面的專輯圖浮動旋轉效果是我最驚喜的了,之前只是想加個陰影,沒想到陰影可以跟隨旋轉,賊帥。

  感謝可愛的你看了這篇博客

  附Github:https://github.com/fengjirong/musicByfeng

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM