需求描述:
1.正常播放音頻
2.可以滑動進度條
3.可以切換上一條,下一條音頻
4.退出目前頁或關閉小程式之後仍然可以正常播放
5.試聽功能進入該播放頁不可以播放上一條,下一條
6.退出該頁面或小程式之後,再次回到該頁面,播放條自動到目前播放進度
圖二圖三是關閉小程式之後微信頁面的展示,可以通過懸浮關閉該音頻。
⚠️ 使用小程式 BackgroundAudioManager,需要在 app.json配置相關參數
"requiredBackgroundModes": [
"audio"
]
代碼
{{music.start}}
{{music.leave}}
// pages/audioPlayer/audioPlayer.js
const api = require('../../service/http.js');
const util = require('../../utils/util.js')
var App = getApp()
const bgMusic = App.bgMusic //建立背景音樂
Page({
data: {
isTry: null, // 是否是試聽狀态
idx: 0, // 目前音頻(第一個-上一條按鈕不能點選,最後一條,下一條按鈕不能點選)
albumCode: '', // 目前音頻辨別
opusName: '', // 目前專輯名字
musicSrc: '',
singler: '', // 目前作者
audioMsg: {}, // 音頻資訊(作者,封面,名字--僅展示)
opusSalt: '', // 目前音頻id
isEnd: false, // 最後一條音頻結束時控制
endVideoTime: '', // 最後一條音頻時長
isPlay: true, // 是否暫停音樂
isStop: false, // 是否停止音樂
slideLen: 0, // 進度條初始值
music: { // 音頻資訊--用來處理資料
start: '00:00',
leave:'',
long: '',
length: ''
},
hasPre: true, // 是否有上一條音頻
hasNxt: true, // 是否有下一條音頻
musicList: [], // 用來存儲音頻清單,存儲到本地,點選上一條、下一條音頻時,不調用接口
perMusicMsg: {}, // 進入頁面之後,就将上一條音頻,下一條音頻資訊提取出來,友善直接點選按鈕
nxtMusicMsg: {}, // 同上
isStopSlider: false // 是否停止滾動條随着音頻播放改變長度 -- 防止拖動滾動條時發生回退現象!!!
},
onLoad: function (options) {
let book
try {
let value = wx.getStorageSync('ai_cloud_book')
if (value) {
book = JSON.parse(value)
}
} catch (e) {
// Do something when catch error
}
this.setData({
albumCode: decodeURIComponent(options.albumCode),
musicSrc: decodeURIComponent(options.playerUrl),
opusName: decodeURIComponent(options.playerName),
singler: decodeURIComponent(options.playerSinger),
isTry: Boolean(Number(options.isTry)),
audioMsg: book,
opusSalt: options.opusSalt,
idx: Number(options.idx),
'music.long': util.formatM(options.playerLong),
'music.length': options.playerLong,
})
},
onReady: function () {
// 正在播放-進入(重新進入目前頁面時)
// this.data.opusSalt === App.globalData.opusSalt 判斷從清單進入時,想要播放的和正在播放的是否為同一條音頻
if(bgMusic.src && this.data.opusSalt === App.globalData.opusSalt) {
this.audioInitAgain()
} else {
// 進入的和之前播放的不是同一條音頻 存儲将要播放的音頻id,并擷取将要播放的音頻資料,然後播放
App.globalData.opusSalt = this.data.opusSalt
this.getAudioSrc()
}
// 試聽隻能聽第一條,上一條,下一條按鈕不可點選
if(this.data.isTry) {
this.setData({
hasPre: false,
hasNxt: false
})
} else {
this.musicListHandle()
}
},
// 跳轉專輯清單-- 傳回上一頁面
jumpAudioList: function() {
wx.navigateBack()
},
// 擷取音頻資訊
getAudioSrc: function() {
bgMusic.src = this.properties.musicSrc
bgMusic.title = this.data.opusName
bgMusic.epname = this.data.opusName
bgMusic.singer = this.data.singer
// 最後一條音樂存儲一下音樂時長--- 播放結束後,不自動跳轉下一條音頻,播放按鈕變為暫停,滾動條置0,endVideoTime展示該音頻時長
this.setData({
endVideoTime: this.data.music.long
})
this.audioInitPlay()
},
// 音頻-暫停/播放
// isPlay: true: 播放狀态 false:暫停狀态
// isStop:true :當不在播放頁面時,點選關閉懸浮框的關閉按鈕 false: 懸浮框未關閉 --- 實際監聽時,監聽不到懸浮框關閉,但依然保留了該字段
ppAudio: function (e) {
let _isPlay = this.data.isPlay
let _isStop = this.data.isStop
if(_isStop) {
this.getAudioSrc()
this.setData({
isPlay: true,
isStop: false
})
return
}
if(_isPlay) {
this.pauseAudio()
} else if(this.data.isEnd){
// 最後一條音頻 - 再次播放需要重新初始化
this.setData({
isEnd: false
})
this.getAudioSrc()
} else {
this.playAudio()
}
this.setData({
isPlay: !_isPlay
})
},
// 音頻實時資訊 -->
audioTimeUpdated: function (e) {
const startTime = e.currentTime
const leaveTime = e.duration - startTime
this.setData({
"music.start": util.formatM(startTime),
"music.leave": util.formatM(leaveTime)
})
if(!this.data.isStopSlider) {
const proLen = (e.currentTime / e.duration * 100).toFixed(2)
this.setData({
slideLen: proLen
})
}
},
// 禁止播放條随着音樂播放滾動
stopSlider: function () {
this.setData({
isStopSlider: true
})
},
// 音頻播放條改變 - 手動滑動滾動條停止
timeSliderChanged: function (e) {
this.setData({
isStopSlider: false
})
if (!this.data.music.length)
return;
var time = this.data.music.length * e.detail.value / 100;
// 音頻跳轉到指定位置
bgMusic.seek(time)
},
// 開始播放-首次進入
audioInitPlay: function () {
App.globalData.opusSalt = this.data.opusSalt
//監聽音樂自然播放結束
bgMusic.onEnded(() => {
// 如果沒有下一個直接指派并禁止播放
if(!this.data.hasNxt) {
let _endTime = this.data.endVideoTime
let idx = 0
let _timer = setInterval(()=>{
if(idx > 1) {
clearInterval(_timer)
}
this.setData({
isPlay: false,
isEnd: true,
"music.start": "00:00",
"music.leave": _endTime
})
console.log(this.data.music)
idx ++
}, 50)
} else {
this.playNxt()
}
})
//監聽音樂播放
bgMusic.onPlay(() => {
console.log('onPlay')
if(this.data.music.start == "00:00") {
this.setData({
"music.leave": util.formatM(bgMusic.duration),
isPlay: true
})
}
this.playAudio()
})
// 監聽背景音頻暫停事件
bgMusic.onPause(() => {
this.setData({
isPlay: false
})
// App.globalData.opusSalt = 0
})
//監聽背景音頻停止事件 --- 實際監聽時,監聽不到懸浮框關閉,但依然保留了該字段
bgMusic.onStop(() => {
this.stopAudio()
App.globalData.opusSalt = 0
})
},
// 開始播放-重複進入
audioInitAgain: function() {
// true - 暫停中 false - 播放中
this.setData({
endVideoTime: util.formatM(bgMusic.duration)
})
console.log(this.data.endVideoTime)
if(bgMusic.paused) {
bgMusic.play()
let timer = setTimeout(() => {
clearTimeout(timer)
//監聽音樂播放
bgMusic.onPlay(() => {
this.playAudio()
})
}, 30)
} else {
bgMusic.onTimeUpdate(() => {
this.audioTimeUpdated(bgMusic)
})
}
},
//暫停
pauseAudio: function () {
bgMusic.pause();
},
// 繼續播放
playAudio: function () {
// 監聽音頻播放進度
bgMusic.onTimeUpdate(() => {
this.audioTimeUpdated(bgMusic)
})
bgMusic.play() //播放音樂
},
// 背景音樂浮窗關閉,重置資料 -- 實際監聽不到懸浮框關閉事件
stopAudio: function() {
this.setData({
isStop: true,
isPlay: false,
"music.start": "00:00",
"music.leave": this.data.music.long,
slideLen: 0
})
},
// 上一首
playPer() {
if(!this.data.hasPre) return
wx.redirectTo({
url: `XX/audioPlayer?albumCode=${encodeURIComponent(this.data.albumCode)}&playerUrl=${encodeURIComponent(this.data.perMusicMsg.opusUrl)}&playerName=${encodeURIComponent(this.data.perMusicMsg.opusName)}&playerSinger=${encodeURIComponent(this.data.singer)}&playerLong=${this.data.perMusicMsg.opusLength}&opusSalt=${this.data.perMusicMsg.opusSalt}&idx=${this.data.idx - 1}&isTry=0`
})
},
// 下一首
playNxt() {
if(!this.data.hasNxt) return
wx.redirectTo({
url: `XXX/audioPlayer?albumCode=${encodeURIComponent(this.data.albumCode)}&playerUrl=${encodeURIComponent(this.data.nxtMusicMsg.opusUrl)}&playerName=${encodeURIComponent(this.data.nxtMusicMsg.opusName)}&playerSinger=${encodeURIComponent(this.data.singer)}&playerLong=${this.data.nxtMusicMsg.opusLength}&opusSalt=${this.data.nxtMusicMsg.opusSalt}&idx=${this.data.idx + 1}&isTry=0`
})
},
// 音樂資料處理
musicListHandle() {
try {
let value = wx.getStorageSync('ai_cloud_book_album')
if (value) {
let _book = JSON.parse(value)
let _hasPer = Boolean(this.data.idx)
let _hasNxt = this.data.idx === _book.length - 1 ? 0 : 1
let _perMusicMsg = {}
let _nxtMusicMsg = {}
if(_hasPer) _perMusicMsg = _book[this.data.idx - 1]
if(Boolean(_hasNxt)) _nxtMusicMsg = _book[this.data.idx + 1]
this.setData({
musicList: _book,
hasPre: _hasPer,
hasNxt: Boolean(_hasNxt),
perMusicMsg: _perMusicMsg,
nxtMusicMsg: _nxtMusicMsg
})
}
} catch (e) {
// Do something when catch error
}
// wx.setStorageSync("ai_cloud_book_album", JSON.stringify(this.data.listenList))
}
})
音頻-暫停/播放(資訊配置) ppAudio()
音頻實時資訊 audioTimeUpdated()
音頻播放條改變 timeSliderChanged()
開始播放-首次進入 audioInitPlay()
開始播放-重複進入 audioInitAgain()
暫停 pauseAudio()
繼續播放 playAudio()
函數作用都已經在注釋裡标注了,有疑問的地方歡迎留言~~