今天專案上涉及到了微信小程式播放音訊功能,所以今天跟著一些教程做了個簡單的播放器
1、實現思路
剛開始想著有沒有現成的元件可以直接用,找到了微信的媒體元件 audio,奈何看著 1.6.0版本開始,該元件不再維護。就百度了一下,還好有另一種方式,使用 InnerAudioContext 來實現音訊播放
2、介面預覽
點選播放,播放按鈕改變為暫停,播放後展示進度條,可 拖動/點選 進度條實現進度控制,可設定倍速
沒有UI設計,所以介面很醜,介面後續完善,功能實現就行啦?
3、介面程式碼
WXML:
1 <view class="item-con"> 2 <block wx:for="{{audios}}" wx:index="idx" wx:item="item" wx:key="idx"> 3 <view class="audio-item"> 4 <view class="audio-info"> 5 <text>{{index+1+"."+item.name}}</text> 6 <view wx:if="{{audioDisplay!=item.id||paused}}" class="audio-btn" bindtap="audioPlay" data-info="{{item}}">播放</view> 7 <view wx:else class="audio-btn btn-pause" bindtap="audioPause">暫停</view> 8 </view> 9 <view class="audio-control" wx:if="{{audioDisplay==item.id}}"> 10 <!-- 時長 --> 11 <view class="audio-number">{{forNowTime?forNowTime:0}}s</view> 12 <slider class="audio-slider" activeColor="#5189FF" block-size="12" value="{{current}}" max="{{duration}}" step="0.01" bindchanging="audioChanging" bindchange="audioChange"> 13 </slider> 14 <view class="audio-number">{{forAllTime?forAllTime:0}}s</view> 15 <!-- 倍速控制 --> 16 <view class="audio-number speed" bindtap="setSpeed"> 17 x{{doubleSpeed}} 18 <view wx:if="{{doubleSpeedSet}}" class="speed-wa" catchtap="setSpeedClose"></view> 19 <view wx:if="{{doubleSpeedSet}}" class="double-speed"> 20 <view class="speed-item" catchtap="setSpeedTo" data-num="0.5">x0.5</view> 21 <view class="speed-item" catchtap="setSpeedTo" data-num="1.0">x1.0</view> 22 <view class="speed-item" catchtap="setSpeedTo" data-num="1.5">x1.5</view> 23 <view class="speed-item" catchtap="setSpeedTo" data-num="2.0">x2.0</view> 24 </view> 25 </view> 26 </view> 27 </view> 28 </block> 29 </view>
JS
1 // 建立音訊播放例項 2 const myAudio = wx.createInnerAudioContext() 3 4 Page({ 5 /** 6 * 頁面的初始資料 7 */ 8 data: { 9 audios: [{ 10 id: 1, 11 name: "秒針", 12 src: "https://sharefs.ali.kugou.com/202202121104/0639f9c2315cbb939aff741be27860ff/KGTX/CLTX001/02c4d6fefd5d899081ba45f47be48adb.mp3" 13 }, 14 { 15 id: 2, 16 name: "做酒", 17 src: "https://sharefs.ali.kugou.com/202202121113/38ab5022041cea53ccff0752d481f818/KGTX/CLTX001/8fa49a75490d252a624c3e1872a26261.mp3" 18 }, 19 { 20 id: 3, 21 name: "好想抱住你", 22 src: "https://sharefs.ali.kugou.com/202202121104/7aa9c439b799ea26ace0fee414aa9c12/KGTX/CLTX001/43f9b75efe102a48ab20131dcaa2b557.mp3" 23 }, 24 { 25 id: 4, 26 name: "紅塵彼岸卻無她", 27 src: "https://sharefs.ali.kugou.com/202202121113/59831d34060f1dfcd2a114e74879868a/KGTX/CLTX001/8a57fbfe87af1dbcac1e9115a2ff1a06.mp3" 28 }, 29 ], 30 // 音訊播放控制 31 audioDisplay: null, //當前播放的音訊,用於顯示播放時長進度條等 32 forNowTime: '0', //當前播放時間 33 forAllTime: '0', //總時長 34 duration: 0, //總時間 秒 35 current: 0, //slider當前進度 36 seek: false, //是否處於拖動狀態 37 paused: true, //是否處於暫停狀態 38 doubleSpeed: 1.0, //播放倍速 預設1.0 39 doubleSpeedSet: false //倍速設定小彈窗 40 }, 41 42 /** 43 * 生命週期函式--監聽頁面載入 44 */ 45 onLoad: function (options) {// 音訊播放初始化 46 this.audioInit() 47 }, 48 49 // 音訊播放-初始化 50 audioInit() { 51 // 設定音訊播放倍速,此處若不設定,頁面上點選設定倍速就不會產生效果 52 myAudio.playbackRate = 1.0 53 // 播放監聽 54 myAudio.onPlay(() => { 55 console.log('開始播放') 56 console.log(myAudio.playbackRate); 57 }) 58 // 暫停監聽 59 myAudio.onPause(() => { 60 console.log('停止播放') 61 }) 62 // 監聽音訊進入可以播放狀態的事件。但不保證後面可以流暢播放,必須要這個監聽,不然播放時長更新監聽不會生效,不能給進度條更新值 63 myAudio.onCanplay(() => { 64 myAudio.duration 65 }) 66 // 播放時長更新監聽 67 myAudio.onTimeUpdate(() => { 68 // 監聽播放進度,更新頁面播放時長和進度條進度 69 this.setData({ 70 forNowTime: parseInt(myAudio.currentTime), 71 forAllTime: parseInt(myAudio.duration), 72 current: myAudio.currentTime, 73 duration: myAudio.duration 74 }) 75 }) 76 // 播放出錯監聽 77 myAudio.onError((res) => { 78 console.log(res.errMsg) 79 console.log(res.errCode) 80 }) 81 }, 82 83 // 開始播放 84 audioPlay(val) { 85 console.log("點選了播放按鈕", val); 86 if (val) { 87 // 展示當前播放音訊的進度條 88 this.setData({ 89 audioDisplay: val.currentTarget.dataset.info.id 90 }) 91 // 設定當前播放音訊的路徑 92 myAudio.src = val.currentTarget.dataset.info.src 93 } 94 // 將暫停狀態賦值為false 95 this.setData({ 96 paused: false, 97 }) 98 // 播放 99 myAudio.play() 100 }, 101 102 // 暫停播放 103 audioPause() { 104 // 將暫停狀態賦值為true 105 this.setData({ 106 paused: true, 107 }) 108 // 暫停 109 myAudio.pause() 110 }, 111 112 // 進度條改變 113 audioChanging(val) { 114 // 通過 seek 來更改當前播放例項的進度 115 myAudio.seek(val.detail.value) 116 // 介面顯示滑動的時間同步改變 117 this.setData({ 118 forNowTime: parseInt(val.detail.value) 119 }) 120 }, 121 122 // 進度條改變完成 123 audioChange(val) { 124 myAudio.seek(val.detail.value) 125 }, 126 127 // 點選設定倍速,彈出小彈窗 128 setSpeed() { 129 this.setData({ 130 doubleSpeedSet: true 131 }) 132 }, 133 134 // 設定倍速的具體值 135 setSpeedTo(val) { 136 // 需要轉換為 Number ,否則不生效 137 myAudio.playbackRate = Number(val.currentTarget.dataset.num) 138 // 介面同步更改並關閉小彈窗 139 this.setData({ 140 doubleSpeed: val.currentTarget.dataset.num, 141 doubleSpeedSet: false 142 }) 143 }, 144 145 // 小彈窗關閉 146 setSpeedClose() { 147 this.setData({ 148 doubleSpeedSet: false 149 }) 150 }, 151 152 /** 153 * 生命週期函式--監聽頁面隱藏 154 */ 155 onHide: function () { 156 // 暫停播放 157 this.audioPause() 158 }, 159 160 /** 161 * 生命週期函式--監聽頁面解除安裝 162 */ 163 onUnload: function () { 164 // 停止播放 165 this.audioPause() 166 myAudio.stop() 167 }, 168 })
4、注意事項
4.1 在初始化的時候需要設定一下播放倍速,不然後面的播放倍速功能可能會不生效
4.2 初始化時,需要配置 InnerAudioContext.onCanplay(function callback) 監聽,不然後續播放時長監聽可能監聽不到
4.3 播放時間和進度條
這裡播放時長和進度條為什麼不用兩個變數來控制
因為獲取到的音訊長度和當前播放位置是小數形式的,我只想進度條用小數來控制,而播放時間想顯示整數,所以用了4個變數,當然也有其他更好的方法,後續會改進
注:其他的暫時沒想到了,記錄一下自己第一次寫部落格