摘要:首先自定義音頻組件,是由於產品有這樣的需求,須要以下樣式的html
而微信小程序API給咱們提供的就是這樣的json
並且產品須要小程序有後臺播放功能,因此咱們不考慮小程序的 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.htmlapi
<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 { 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 */
/** * @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 }
globalData: { userInfo: null, global_bac_audio_manager: { manage: wx.getBackgroundAudioManager(), is_play: false, id: '', play_time: '', article_id: '', } }
總結: 在IOS端 背景音頻播放必須設置title 才能夠播放微信