微信小程序学习之旅--零基础制作自己的小程序-文章详情页音乐播放功能的实现-背景音频/全局App/页面的bug修改和优化

文章目录

  • 微信小程序入门(五)
      • 音乐播放功能
        • 制作样式
        • 背景音频播放
          • 绑定事件
          • 功能测试
          • 控制台报错
        • 切换音乐播放图标
        • 同步音乐控制开关与图标的状态
          • 背景音频对象的播放/暂停事件回调
          • 进一步优化
          • 再一次优化音乐的暂停和停止
        • 音乐播放状态的初始化问题
          • 在优化
        • 分析其它问题
          • 不是问题也是问题的问题
          • 全局变量
          • 文章音乐播放状态
          • 文章音乐暂停和停止
          • onLoad初始化的时候赋值
        • 还未解决的bug
          • 音乐播放完毕,图标不同步
          • 音乐播放时进入其他文章
      • 下一篇

前文
微信小程序学习之旅–第一个页面的制作
微信小程序学习之旅–零基础制作自己的小程序–第二个页面的制作
微信小程序学习之旅–完善pages页面–字体图标,数据绑定,条件/列表渲染,事件/catch/bind以及路由的学习
微信小程序学习之旅–零基础制作自己的小程序-完成文章详情页–自定义属性/页面通信/缓存机制/异步API/async/await

微信小程序入门(五)

音乐播放功能

制作样式

静态样式没啥好说的,基本上有手就行了。

<view class="head-image-audio"><image class="head-image" src="{{imgSrc}}">image><image class="audio" src="/images/music/music-start.png" />view>
/* 大图+音乐播放 */
.head-image-audio {position: relative;height: 460rpx;
}/* 图片 */
.head-image {width: 100%;height: 100%;
}/* 音乐播放 */
.audio {width: 102rpx;height: 110rpx;position: absolute;/* 居中 */left: 50%;top: 50%;transform: translate(-50%, -50%);opacity: .6;
}

image-20210829110147532

我们想要实现的功能就是点击以后实现音乐的播放。

背景音频播放

这里也需要了解一下官方提供的关于背景音频播放的API组件。

绑定事件

老规矩,肯定还是需要在图片上绑定点击事件。

<image bind:tap="onMusic" class="audio" src="/images/music/music-start.png" />
功能测试

这里先简单的使用一下背景音频。

/*** 音乐播放功能* @param {*} event */onMusic(event) {// 获取全局唯一的背景音频管理器。 小程序切入后台,如果音频处于播放状态,可以继续播放。但是后台状态不能通过调用API操纵音频的播放状态const mgr = wx.getBackgroundAudioManager();// 赋值音乐播放的链接mgr.src = this.data.music.url;// 音乐播放的标题mgr.title = this.data.music.title;}

image-20210829112622826

咳咳,很明显,没什么大毛病。用起来也不难。

控制台报错

image-20210829112702351

虽然使用没什么问题,但是控制台给我们了报错提示。这时候,我们去这个地址看看。

为了能够转后台以后可以继续播放音频。我们就在app.json文件中配置一下。

image-20210829112917612

当我们在app.json中配置了这个属性,并且数组里面只有一个值audio时

"requiredBackgroundModes": ["audio"]

音乐播放的同时,切后台音乐也会一直播放。

而只使用location这个值,只有在小程序没有退出的时候才会一直播放,一旦切后台,音乐就会停止。

"requiredBackgroundModes": ["location"]

我们这里就把两个值都加上吧。

"requiredBackgroundModes": ["audio","location"]

切换音乐播放图标

因为需要进行音乐播放与停止的切换,所以图标也需要更改。

<image wx:if="{{!isPlaying}}" bind:tap="onMusicStart" class="audio" src="/images/music/music-start.png" /><image wx:else bind:tap="onMusicStop" class="audio" src="/images/music/music-stop.png" />
/*** 音乐播放开始功能* @param {*} event */onMusicStart(event) {// 获取全局唯一的背景音频管理器。 小程序切入后台,如果音频处于播放状态,可以继续播放。但是后台状态不能通过调用API操纵音频的播放状态const mgr = wx.getBackgroundAudioManager();// 赋值音乐播放的链接mgr.src = this.data.music.url;// 音乐播放的标题mgr.title = this.data.music.title;// 播放时使用的图片mgr.coverImgUrl = this.data.music.coverImg;// 切换当前音乐的播放状态为 播放中this.setData({isPlaying: true});},/*** 音乐暂停的事件处理* @param {*} event */onMusicStop(event) {const mgr = wx.getBackgroundAudioManager();// 音乐停止mgr.stop();// 音乐状态的切换this.setData({isPlaying:false})},

说实话,这样的确达到了音乐的停止和播放之间状态的切换。但是,你会发现每次切换播放和暂停音乐以后,音乐需要重新播放、并且,如果在音乐播放的时候,我们点击下面的控制面板,可以发现,音乐暂停了,但是图标不会自动切换。问题还是很多。

image-20210829141418289

同步音乐控制开关与图标的状态

背景音频对象的播放/暂停事件回调

很明显,想要达到我们需要的某些状态,肯定是需要使用音频对象提供的某些回调函数。

image-20210829142040225

所以我们通过这两个事件,来根据音乐的播放和暂停调用不同的函数。

进一步优化

因为我们会在很多地方都使用到这个背景音频的对象,所以我们将其放到data数据源中,并且在页面加载的时候进行获取,同时在onLoad中监听音乐的播放和暂停两个事件。

/*** 页面的初始数据*/data: {post: {},// 记录当前文章的id_pid: null,// 当前文章是否收藏collected: false,// 所有文章是否收藏的缓存对象_postsCollected: {},// 音乐是否播放中isPlaying: false,// 背景音频对象_mgr: null},/*** 生命周期函数--监听页面加载*/async onLoad(options) {// 通过监听页面加载的的函数的参数options,机也可以拿到我们传递过来本页面的参数// 注意:查询字符串(参数)的类型都是字符串类型// console.log(options);const [post] = [...postList.filter(post => post.postId === parseInt(options.pid))];// 记录文章idthis.data._pid = post.postId;// console.log(post);// 拿到我们指定的文章this.setData(post);// 读取缓存,拿到文章是否收藏的状态const { data: postsCollected } = await wx.getStorage({key: 'post_collected',})// 记录所有文章的缓存状态的对象this.data._postsCollected = postsCollected;// 拿到当前文章的收藏状态 取不到则表示这篇文章未收藏const collected = postsCollected[this.data._pid] || false;// console.log(postsCollected);// console.log(collected);this.setData({ collected });const mgr = wx.getBackgroundAudioManager();this.data._mgr = mgr;// 监听背景音乐的播放和停止// mgr.onPlay(()=>{//   // 音乐播放//   this.onMusicStart();// });mgr.onPlay(this.onMusicStart);// 音乐暂停的回调处理mgr.onPause(this.onMusicStop);},/*** 文章收藏点击事件的回调* @param {*} event  事件对象*/async onCollect(event) {const postCollected = this.data._postsCollected;// 当前文章的收藏状态 取不到则肯定没有收藏过const collected = postCollected[this.data._pid] || false;// 用文章id的值作为实际存储对象的属性,属性值是是否收藏postCollected[this.data._pid] = !collected;wx.setStorageSync('post_collected', postCollected)this.setData({// 这里直接取反就可以了 上面的执行完毕这里可以直接取反了collected: !collected});// 使用小程序默认的API 弹框组件来提示用户是收藏文章 还是取消收藏wx.showToast({// 提示文字title: this.data.collected ? "收藏文章成功!" : "取消收藏成功!",// 提示框停留时间duration: 2000})},/*** 完成文章分享的回调函数* @param {*} event */onShare(event) {// 调用小程序原生的组件 实现分享wx.showActionSheet({// 分享的方式(具体分享以后做什么,我们并没有做)itemList: ["分享到QQ", "分享到微信", "分享到微博", "分享到朋友圈"],success(res) {// 通过 res.tapIndex 可以拿到我们点击了哪一个数组元素的索引// 想做其他事情可以做// console.log(res.tapIndex);}})},/*** 音乐播放开始功能* @param {*} event */onMusicStart(event) {const mgr = this.data._mgr;// 赋值音乐播放的链接mgr.src = this.data.music.url;// 音乐播放的标题mgr.title = this.data.music.title;// 播放时使用的图片mgr.coverImgUrl = this.data.music.coverImg;// 切换当前音乐的播放状态为 播放中this.setData({isPlaying: true});},/*** 音乐暂停的事件处理* @param {*} event */onMusicStop(event) {const mgr = this.data._mgr;// 音乐停止mgr.stop();// 暂停播放// mgr.pause();// 音乐状态的切换this.setData({isPlaying: false})},

image-20210829144141275

这样就可以完成音乐的停止和播放之间的切换了。

但是,这样做我们音乐就直接停止了,用户点击的是暂停按钮,按理说我们要做的应该是让音乐暂停,而不是直接终止。

很显然,用户点击控制面板的暂停,应该就是让音乐暂停,而不是直接停止。

所以说,我们要做的,应该是点击我们自己的按钮,实现的是音乐的播放和停止,而用户点击下面的控制面板,应该是在播放和暂停之间切换。

再一次优化音乐的暂停和停止

话都说的这么明白了,接下来不用我说,有手就行了。

这里将音乐停止的函数进行改进。

/*** 音乐暂停的事件处理* @param {*} isStop 停止音乐 */onMusicStop(isStop = true) {// const mgr = wx.getBackgroundAudioManager();const mgr = this.data._mgr;if (isStop) {// 音乐停止mgr.stop();} else {// 暂停播放mgr.pause();}// 音乐状态的切换this.setData({isPlaying: false})},async onLoad(options) {// 省略 。。。const mgr = wx.getBackgroundAudioManager();this.data._mgr = mgr;mgr.onPlay(this.onMusicStart);// 音乐暂停的回调处理mgr.onPause(this.onMusicStop.bind(this,false));
}

这就达到了我们想要的效果。点击下面的控制面板,音乐暂停;点击上面图片按钮,音乐由播放转为停止。

image-20210829145522243

音乐播放状态的初始化问题

当我们解决了上面的问题之后,接下来其实很有其他问题。

image-20210829150048411

当我们点击返回按钮,此时音乐还是处于播放状态,因为我们没有停止播放。再次进行本页面的时候,这个音乐还是播放中,但是我们的图标和下面音乐的状态对不上了。

image-20210829151024017

原因当然很明显,是我们的状态问题,每次我们页面的加载时,状态都被重置为false。

这里我们可以采用全局变量的方式,来记录音乐的播放与否。没必要使用缓存,因为缓存是持久化的。实际上程序退出了就没必要管音乐的事情了。

在优化

这思路就很简单了。搞一个全局变量,每次在音乐状态切换的同时,我们全局的状态跟着改变。

// app.jsApp({// 记录音乐的播放状态gIsPlayingMusic:false
})
// // pages/post-detail/post-detail.js// 全局的小程序对象,用来获取我们的全局变量
const app = getApp()Page({onLoad(){// 获取全局记录的播放状态this.setData({isPlaying: app.gIsPlayingMusic});},/*** 音乐播放开始功能* @param {*} event */onMusicStart(event) {// 改变全局的音乐播放状态app.gIsPlayingMusic = true;},/*** 音乐暂停的事件处理* @param {*} isStop 停止音乐 */onMusicStop(isStop = true) {// 改变全局的音乐播放状态app.gIsPlayingMusic = false;}
})

其它代码都不在赘述。

image-20210829152951445

分析其它问题

不是问题也是问题的问题

老实说,改了这么多,还是有一些小的bug。刚解决一个又来一个。

这个问题说是问题,也可以说不是问题。

就是我们发现,我们当前文章的歌曲在播放,然后我们退出去进入其他页面,按理说其他页面的歌曲和我们这个是不一样的歌曲,应该是不应该让音乐按钮显示播放状态的,但是我们每次获取的状态都是全局的,所以导致只要有音乐在播放,进去其他文章也都是会显示播放状态。

这个问题你说是问题,其实也没错,本来就是bug。你要是说不是问题,也没毛病,本来就是有音乐就是在播放中。

这里我理解呢是bug。就简单的解决一下。

思路还是那么明显,搞个全局变量就完事。弄一个全局变量记录当前音乐播放是属于那篇文章的。这样在赋值播放状态的时候,我们就可以根据文章的id号是否相同,来解决这个问题。

全局变量
// app.js// 记录音乐的播放状态gIsPlayingMusic: false,// 记录播放的音乐是属于那篇文章的 默认是-1gIsPlayingPostId: -1
文章音乐播放状态
/*** 当前文章的音乐播放状态 * * @returns 只有音乐所属的文章号是当前所在的文章页面,且音乐一直处于播放状态, 返回true*/currentPostMusicIsPlaying() {if (app.gIsPlayingMusic && this.data._pid === app.gIsPlayingPostId)return true;return false;}
文章音乐暂停和停止

音乐暂停的逻辑不需要改变,音乐停止的逻辑进行修改

/*** 音乐暂停的事件处理* @param {*} isStop 停止音乐 */onMusicStop(isStop = true) {const mgr = this.data._mgr;if (isStop) {// 音乐停止mgr.stop();// 音乐停止,重置全局音乐的文章idapp.gIsPlayingPostId = -1;} else {// 暂停播放mgr.pause();}// 音乐状态的切换this.setData({isPlaying: false})// 改变全局的音乐播放状态app.gIsPlayingMusic = false;}
onLoad初始化的时候赋值
onLoad(){// 音乐播放状态 只有音乐所属的文章号是当前所在的文章页面,且音乐一直处于播放状态,我们才重置音乐的播放状态为truethis.setData({isPlaying: this.currentPostMusicIsPlaying()});
}

image-20210829162601019

还未解决的bug

解决了很多问题。但是还是存在一些问题。

音乐播放完毕,图标不同步

当我们音乐播放完毕后,上面的图标并没有同步的进行状态的切换,音乐都播放完了,按理说状态应该是未播放。

音乐播放时进入其他文章

表面上,我们解决了这些问题,但是进去其他页面的时候,如果我们点击了音乐的暂停,这很ok。如果暂停后再次点击播放,播放的音乐就变成当前文章的背景音乐了。我觉得这也不是很合理的。

bug很多。头疼。

下一篇

微信小程序入门之旅-第六天-自定义组件及request的使用-制作电影页面


本文来自互联网用户投稿,文章观点仅代表作者本人,不代表本站立场,不承担相关法律责任。如若转载,请注明出处。 如若内容造成侵权/违法违规/事实不符,请点击【内容举报】进行投诉反馈!

相关文章

立即
投稿

微信公众账号

微信扫一扫加关注

返回
顶部