摘要:首先自定義音訊元件,是因為產品有這樣的需求,需要如下樣式的
而微信小程式API給我們提供的就是這樣的
而且產品需要小程式有後臺播放功能,所以我們不考慮小程式的 audio 元件,即使官方推薦更強大的 wx.createInnerAudioContext 但是不符合需求,所以這裡用到的是 backgroundAudioManager()
https://developers.weixin.qq.com/miniprogram/dev/api/getBackgroundAudioManager.html
分析一下:這個頁面構成,主要就是進度條和一些icon,進度條之前我自定義了一版,但是效果不理想,最後重構了頁面,所以這裡用的就是 slider 滑動選擇器 https://developers.weixin.qq.com/miniprogram/dev/component/slider.html
- audio.wxml
<view class="audio">
<image class="bg" src="{{audio_article.lessonImg}}"></image>
<image mode="aspectFill" class="poster" src="{{audio_article.lessonImg}}"></image>
<view class="control-process">
<text class="current-process">{{current_process}}</text>
<slider class="slider"
bindchange="hanle_slider_change"
bindtouchstart="handle_slider_move_start"
bindtouchend="handle_slider_move_end"
min="0"
block-size="16"
max="{{slider_max}}"
activeColor="#fff"
backgroundColor="rgba(255,255,255,.3)"
value="{{slider_value}}"
/>
<text class="total-process">{{total_process}}</text>
</view>
<view class="icon-list ">
<image bindtap="prev" mode="widthFix" src="{{is_first_page?'/images/audio_prev_no.png':'/images/audio_prev.png'}}" class="audio-icon"></image>
<image mode="widthFix" src="{{is_play? '/images/audio_play.png': '/images/audio_paused.png'}}" class="audio-icon audio-play" bindtap="audio_play"></image>
<image bindtap="next" mode="widthFix" src="{{is_last_page?'/images/audio_next_no.png':'/images/audio_next.png'}}" class="audio-icon"></image>
<image hidden mode="widthFix" class="pattern" src="{{is_loop ? '/images/audio_loop.png': '/images/audio_un_loop.png'}}" bindtap="play_loop"></image>
</view>
</view>
複製程式碼
滑動事件 bindchange="hanle_slider_change"
開始滑動 bindtouchstart="handle_slider_move_start"
停止滑動 bindtouchend="handle_slider_move_end"
複製程式碼
- audio.wxss
.audio {
position: relative;
width: 750rpx;
height: 640rpx;
padding: 60rpx 32rpx 52rpx;
box-sizing: border-box;
text-align: center;
overflow: hidden;
background: rgba(0,0,0,.18);
}
.audio .bg {
position: absolute;
top: 0;
left: -100%;
bottom: 0;
right: 0;
margin: auto;
width: 300%;
height: 300%;
z-index: -1;
filter: blur(40rpx);
}
.editor {
padding: 32rpx;
box-sizing: border-box;
color: #333;
font-size: 28rpx;
background: #fff;
}
.editor view {
max-width: 100% !important;
}
.audio .poster {
width: 238rpx;
height: 336rpx;
}
/* 音訊滾動條start */
.control-process {
margin-top: 20rpx;
display: flex;
justify-content: space-between;
align-items: center;
}
.control-process .slider {
width: 526rpx;
}
.control-process text {
font-size: 24rpx;
color: #fff;
}
/* 音訊滾動條end */
.audio .icon-list {
position: relative;
margin: 0 auto;
line-height: 102rpx;
}
.audio .icon-list .audio-icon + .audio-icon {
margin-left: 72rpx;
}
.audio .icon-list .pattern {
position: absolute;
right: 20rpx;
}
.audio image {
width: 64rpx;
height: 64rpx;
vertical-align: middle;
}
.audio .audio-play {
width: 92rpx;
height: 92rpx;
}
.audio .pattern {
position: absolute;
top: 0;
bottom: 0;
margin: auto 0;
width: 44rpx;
height: 44rpx;
}
/* 音訊end */
複製程式碼
- audio.js
/**
* @author: 清風白水 https://www.cnblogs.com/luxiaoyao/
* @date: 2018/07/20 14:36:00
* @program: 重構音訊頁面
*/
const APP = getApp()
const AUDIOMANAGER = getApp().globalData.global_bac_audio_manager.manage
const AUDIO = getApp().globalData.global_bac_audio_manager
Page({
onLoad: function (e) {
let that = this,
request_param = {
articleId: e.articleId
}
this.setData({
article_id: e.articleId
})
wx.request({
url: 'your url',
method: 'POST',
data: {},
header: {
'Content-Type': 'application/json;text/html;charset=utf-8;'
},
success: (res) => {
if (res.data.code == 'A00000') {
AUDIOMANAGER.onPlay(() => {
setTimeout(() => {
that.setData({
is_loading: true
})
}, 300)
})
let response = res.data.data.information
// 如果不是從懸浮按鈕播放,就重新賦值
if (e.articleId == AUDIO.id && AUDIO.is_play) {
wx.seekBackgroundAudio({
position: Math.floor(AUDIO.time)
})
} else {
audio_background_play(response)
}
// 置灰上一首下一首
if (response.preArticleId == 0) {
that.setData({
is_first_page: true
})
}
if (response.nextArticleId == 0) {
that.setData({
is_last_page: true
})
}
}
}
})
//背景音訊播放進度更新事件
AUDIOMANAGER.onTimeUpdate(() => {
if (!that.data.is_moving_slider) {
that.setData({
current_process: format(AUDIOMANAGER.currentTime),
slider_value: Math.floor(AUDIOMANAGER.currentTime),
total_process: format(AUDIOMANAGER.duration),
slider_max: Math.floor(AUDIOMANAGER.duration)
})
}
AUDIO.time = AUDIOMANAGER.currentTime
})
// 背景音訊播放完畢
AUDIOMANAGER.onEnded(() => {
if (!that.data.is_loop) {
that.next()
} else {
// 單曲迴圈
that.setData({
slider_value: 0,
current_process: '00:00',
})
audio_background_play(response)
}
})
},
// 拖動進度條,到指定位置
hanle_slider_change(e) {
const position = e.detail.value
this.seekCurrentAudio(position)
},
// 拖動進度條控制元件
seekCurrentAudio(position) {
// 更新進度條
let that = this
wx.seekBackgroundAudio({
position: Math.floor(position),
success: function () {
AUDIOMANAGER.currentTime = position
that.setData({
current_process: format(position),
slider_value: Math.floor(position)
})
}
})
},
// 進度條滑動
handle_slider_move_start() {
this.setData({
is_moving_slider: true
});
},
handle_slider_move_end() {
this.setData({
is_moving_slider: false
});
},
// 點選播放暫停
audio_play: function () {
let that = this
if (this.data.is_play) {
that.setData({
is_play: false
})
wx.pauseBackgroundAudio()
} else if (!this.data.is_play && this.data.is_ended) { // 這裡是判斷如果迴圈播放結束,沒有下一首,重新播放 is_ended 是否是最後一首
audio_background_play(that.data.audio_article)
that.setData({
is_play: true,
is_ended: false
})
} else if(!this.data.is_play){
that.setData({
is_play: true
})
wx.playBackgroundAudio()
}
AUDIO.is_play = !AUDIO.is_play
},
// 點選是否迴圈
play_loop: function () {
let that = this
if (this.data.is_loop) {
that.setData({
is_loop: false
})
} else {
that.setData({
is_loop: true
})
}
},
// 上一首
prev: function () {
let that = this
if (that.data.audio_article.preArticleId != 0) {
wx.redirectTo({
url: '/pages/audio_article/audio_article?articleId=' +
that.data.audio_article.preArticleId
})
}
},
// 下一首
next: function () {
let that = this
if (that.data.audio_article.nextArticleId != 0) {
wx.redirectTo({
url: '/pages/audio_article/audio_article?articleId=' +
that.data.audio_article.nextArticleId
})
} else { // 如果是最後一首
that.setData({
is_play: false,
slider_value: 0,
current_process: '00:00',
is_ended: true
})
AUDIO.is_play = false
}
},
onUnload: function () {
// 動態切換懸浮按鈕的動態
if (AUDIO.is_play) {
APP.globalData.is_active = true
} else {
APP.globalData.is_active = false
}
}
})
// 時間格式化
function format(t) {
let time = Math.floor(t / 60) >= 10 ? Math.floor(t / 60) : '0' + Math.floor(t / 60)
t = time + ':' + ((t % 60) / 100).toFixed(2).slice(-2)
return t
}
// 音訊播放
function audio_background_play(response) {
AUDIOMANAGER.src = response.urlCompressed ? response.urlCompressed : response.audioLink // 音訊的資料來源,預設為空字串,當設定了新的 src 時,會自動開始播放 ,目前支援的格式有 m4a, aac, mp3, wav
AUDIOMANAGER.title = response.articleName // 音訊標題
AUDIOMANAGER.epname = response.lessonName // 專輯名
AUDIOMANAGER.singer = '****' // 歌手名
AUDIOMANAGER.coverImgUrl = response.poster // 封面圖url
}
複製程式碼
- app.js
globalData: {
userInfo: null,
global_bac_audio_manager: {
manage: wx.getBackgroundAudioManager(),
is_play: false,
id: '',
play_time: '',
article_id: '',
}
}
複製程式碼
總結: 在IOS端 背景音訊播放必須設定title 才可以播放
更多文章關注 : https://www.cnblogs.com/luxiaoyao/