微信小程序从入坑到放弃二十八:开发一款DIY音乐播放器(WXS优化版)
0
阅: - 评:0 - 积分:摘要:前天,我们初步开发了一款可控制播放进度的音乐播放器。但在真机上运行时会略显卡顿,为了解决性能问题,今天我们使用WXS来改进代码。主要思路是:WXS负责处理交互逻辑并格式转换,组件用来与页面实现数据双向通信......
书接上回,在前天的文章中,我们初步开发了一款自定义音乐播放器,但存在性能问题,详情阅读原文《微信小程序从入坑到放弃二十七:可控制播放进度的音乐播放器(初级版)》。今天,我们就来优化下代码,以提高性能。
一、卡顿原因分析
1.1、格式转换
首先,音频播放的时间是数字格式,但界面展示是时间格式,所以我们会进行格式转换。与此同时,时间轴滚动的距离是px
,所以我们还要根据比例算出距离px
。如图:音乐播放器中时间轴和当前播放时间是动态变化的.png
1.2、diyAudioPlayer.js中包含了大量的交互
其次,所有的格式转换及单位换算全都在diyAudioPlayer.js
中,且每秒都在计算。除此之外,拖拽操作也非常影响性能,所以卡顿自然就能理解了。
二、解决方案:WXS辅助
使用WXS的好处就是为了把复杂的运算逻辑及交互操作拎出来以解决提高性能。那如何把WXS
运用到在此案例中呢?在说答案前,有必要先了解WXS
的特性及限制条件!
2.1、了解WXS
使用 WXS
函数用来响应小程序事件,目前只能响应内置组件的事件,不支持自定义组件事件。WXS
函数的除了纯逻辑的运算,还可以通过封装好的ComponentDescriptor
实例来访问以及设置组件的 class
和样式,对于交互动画,设置 style
和 class
足够了。
更详情介绍参见微信小程序官方文档:WXS响应事件
从上面的一段话中,我们大致知道了WXS
的局限性,其闪光点儿并不明显,继续往下说。
2.2、逐步分析,取舍有度
在整个音乐播放器中,有以下变量:currentTime
:当前音频播放位置(动态改变,包括拖拽过程中);durationValue
:当前音频的长度(固定值,不会发生变化);progressWidthValue
:时间轴的有效长度(固定值,不会发生变化);x
:滑块在x轴方向上运动的距离(动态改变,可根据前三个参数计算得出);
所以,最主要的还是解决currentTime
!
currentTime
的值发生变化有两种情况:
情况一:音频播放过程中;
情况二:拖拽滑块的过程中。
在情况二中,虽然我们可以通过event.changedTouches[0].startX
计算出来,但由于WXS无法做到数据双向绑定。所以,在touchMove
过程中要通过ins.callMethod('touchMove', { currentTime: currentTime })
来通知组件,由组件来动态更新currentTime
的值。核心代码如下:
- /* 监听拖拽 */
- function touchMove(event, ins) {
- var touch = event.touches[0] || event.changedTouches[0]
- var pageX = touch.pageX
- left = pageX - startX + lastLeft
- /* 滑块运动的最小范围 */
- if (left >= 0) {
- left = 0
- }
- /* 滑块运动的最大范围 */
- if (left < progressWidthValue) {
- left = progressWidthValue
- }
- startX = pageX
- lastLeft = left
- currentTime = getcurrentTime() /* 计算出音频的播放位置(虽然此处能计算出,但不能直接跟页面通信,所以必须要靠下一行实现响应数据) */
- ins.callMethod('touchMove', { currentTime: currentTime }) /* 向组件通信 */
- }
- /* 组件中监听拖拽 */
- touchMove(data) {
- if (data && !data.target && data.currentTime !== undefined) {
- this.setData({
- currentTime: data.currentTime /* 接收wxs中计算出的值并利用setData实现数据响应 */
- })
- }
- }
最终的wxml
页面代码如下:
- <!-- 引入WXS start -->
- <wxs src="./wxs-diyAudioPlayer.wxs" module="wxs"></wxs>
- <!-- 引入WXS end -->
- <view class="my-audio">
- <view class="audio-box">
- <!-- 播放/暂停的图标 start -->
- <image class="audio__status" src="\{\{isPlay ? pauseSrc : playSrc\}\}" mode="widthFix" bindtap="\{\{isPlay ? 'goPause' : 'goPlay'\}\}"></image>
- <!-- 播放/暂停的图标 end -->
- <view class="audio__content">
- <view class="audio__progress">
- <movable-area class="audio__progress-movable">
- <movable-view class="audio__progress_bar \{\{isCanplay ? '' : 'audio__progress_loading'\}\}" direction="horizontal" x="\{\{wxs.changeX(currentTime,durationValue,progressWidthValue)\}\}" change:progresswidth="\{\{wxs.propProgressWidth\}\}" progresswidth="\{\{progressWidthValue\}\}" change:duration="\{\{wxs.propDuration\}\}" duration="\{\{durationValue\}\}" bindtouchmove="\{\{wxs.touchMove\}\}" bindtouchend="\{\{wxs.touchEnd\}\}" bindtouchstart="\{\{wxs.touchStart\}\}" animation="\{\{false\}\}"> \{\{wxs.formatTime(currentTime)\}\}/\{\{wxs.formatTime(durationValue)\}\}
- <!-- 按住拖拽时的tips start -->
- <view class="audio__progress_tips" wx:if="\{\{isTouchMove\}\}">\{\{wxs.formatTime(currentTime)\}\}/\{\{wxs.formatTime(durationValue)\}\}</view>
- <!-- 按住拖拽时的tips end -->
- </movable-view>
- </movable-area>
- <!-- 已经播放的进度 start -->
- <view class="audio__progress_current" wx:if="\{\{isProgress\}\}" style="width:\{\{wxs.changeX(currentTime,durationValue,progressWidthValue)\}\}px"></view>
- <!-- 已经播放的进度 end -->
- </view>
- </view>
- </view>
- </view>
友情提示:上面代码中的 \
反斜线是为了防止在文章中转码,看官复制后替换为空即可。
2.3、源码讲解
注意上面代码中黄色高亮的部分,是本次修改的。
对照本文中的2.2
小节可以发现:上一篇文章中的progress
被currentTime
取代;total
被durationValue
取代;x
被wxs.changeX(currentTime,durationValue,progressWidthValue)
取代。
上面第12
行中,touchMove、touchEnd
等事件改为wxs.touchMove
等。事件由WXS
处理,这样一来,代码质量及性能明显有所提高。
第12
行也体现出了组件向WXS通信后WXS监听属性变化的特点。举例说明:
- change:progresswidth="\{\{wxs.propProgressWidth\}\}" progresswidth="\{\{progressWidthValue\}\}"
progresswidth="\{\{progressWidthValue\}\}"
这一句表示的意思是:从index.js
中获取到progressWidthValue
并作为progressWidth
属性的值;change:progresswidth
即监听progressWidth
属性,当progressWidthValue
发生变化时,会触发\{\{wxs.propProgressWidth\}\}
函数,这样就实现了组件与WXS的单向通信。
2.4、总结
现在,组件和WXS之间相互完成了单向通信,各自的职责也很明确。
组件:负责提供值和实现页面间的双向通信;
WXS:负责处理拖拽交互后的值传递给组件,由组件通过setData
来更新。在页面中,继续由WXS
中的函数来进行格式转换。
三、demo源码
demo源码已上传到了github
上,如果看官需要研究源码,可以点击下面的链接进行访问并下载。
四、如何在项目中使用封装好的组件?
若看官想把此款音乐播放器使用到实际项目中,可以先通过上面的链接从github仓库上拉取代码到本地,然后在需要使用的页面中引用组件即可。啥也不说了,还是直接上代码给看官演示一下吧,此处以在小程序首页中调用为例。
4.1、修改index.json配置
- {
- "usingComponents": {
- "wxs-diyAudioPlayer": "/components/wxs-diyAudioPlayer/index"
- },
- "navigationBarTitleText": "开发一款DIY音乐播放器(WXS优化版)"
- }
index.json
配置完毕后,直接在index.wxml
中调用即可。
4.2、在index.wxml页面中调用
- <!-- 音乐播放器 start -->
- <wxs-diyAudioPlayer audioSrc="\{\{audioSrc\}\}"></wxs-diyAudioPlayer>
- <!-- 音乐播放器 end -->
此时,我们还有最后一步:即在index.js
中添加一个网络音频地址。
4.3、在index.js中添加音频地址
- var app = getApp();
- Page({
- data: {
- audioSrc: 'https://card-cdn-test.5ifengdu.com/ali/audio/202002/11/1581416977486_8929949054.mp3' /* 网络音频地址 */
- },
- /* 以下是原项目代码 */
- ......
- });
现在,保存代码即可在微信小程序首页中看到音乐播放器了。最终效果如下:开发一款DIY音乐播放器(WXS优化版)最终效果.mp4(友情提醒:点击上方图片即可播放视频)
五、最后
源码及如何在项目中使用这款音乐播放器的步骤已经很详细了,由于文章篇幅有限,所以文章中的js代码就没有完全展示。源码中会有完整代码及必要注释,若看官在拉完代码后有疑问,可与艺灵联系,方式见下方二维码或右侧。
转载声明:
若亲想转载本文到其它平台,请务必保留本文出处!
本文链接:/xwzj/2020-05-12/weixin-wxs-diyAudioPlayer.html
若亲不想直保留地址,含蓄保留也行。艺灵不想再看到有人拿我的技术文章到他的地盘或者是其它平台做教(装)程(B)而不留下我的痕迹。文章你可以随便转载,随便修改,但请尊重艺灵的劳动成果!谢谢理解。
亲,扫个码支持一下艺灵呗~
Tag: 微信小程序 小程序教程 audio音频 音乐播放器 movable-area WXS 数据通信 prop callMethod wx.createInnerAu
上一篇: 微信小程序从入坑到放弃二十七:可控制播放进度的音乐播放器(初级版) 下一篇: gulp3实战技巧之利用gulp-file-include实现模板复用,大大提高开发效率!