wepy框架中 音频播放整理

本文详细介绍了在小程序中实现音频播放功能的方法,包括播放时间准确性的保证、播放进度的控制等关键技术点。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

先描述一下 我们小程序中音频播放的需求吧

1.有一个课时介绍页面,每节课里面有可能是音频,也有可能是视频,这里是要判断展示一下的很容易,当用户点击了音频播放按钮的时候开始播放,当用户切换到其他的页面的时候有一个悬浮gif图 点击可以进入播放页面。
2.播放页面很简单,像是播放头像旋转啊,播放进度条啊,播放时长持续更新啊之类的,用户在滑动slider的时候可以随意控制播放进度。
3.用户退出小程序的时候音频可以继续在后台播放

功能介绍:

一、如何保证播放时间的准确性
设想一个场景,用户在课时点击了音频开始播放,这时候 用户有两条路,一是点击播放悬浮按钮进入播放页面,二是退出当前页去浏览其他的页面,无论是那条路,最后用户进入 播放页面的时候,如何能保证 从开始播放到 用户进入页面的这个时间段用户播放的时长。。。你不能掐手指头算吧
1.课时页面
用户点击的时候 通过this.$parent.getMusicSeond(this.playTime), 这里在app.wpy中设置了一个叫做 getMusicSecond的函数,他的作用就是用户点击播放时候传个0过去,并且开启全局定时器,记录用户播放的时长。 当用户点击暂停按钮时候 再调用一个 this.$parent.StopMusiceSecond() 用它来关闭全局定时器。
2. 音频播放页面
(只考虑音频播放状态)在用户进入到播放页面的时候,一是要拿到全局音频播放的时间,二是关闭调全局定时器,如果你不关掉然后我们又在播放页面中生成了一个定时器,在乎用户退出页面,在进入的时候……时间是完全错乱的。
通过this.$parent.stopParentTime() 先将全局的定时器关掉,并且返回到现在位置播放的时长,this.$parent.stopParentTime() 要放到 onShow() 而不是放到 onLoad() 他俩的差别具体需要自行查看文档。现在 我们拿到了播放时长和关闭了全局定时器, 下面要做的就是 如何利用这个是时间控制音频播放了
1) 获取播放时长
首先我们把拿到的数据放到 当前组件中的一个自定义变量里面 this.PlayTime = this.$parent.stopParentTime() 。因为需求是要求关闭小程序音频还可以在后台播放,所以我们调用小程序API中的 wx.playBackgroundAudio({}) , 现在播放时间也有了,就差播放链接地址了,ok,频播播放地址,在你刚进入课时详情的时候点击播放的时候就应该给它放到 app.wpy 中, 这样我们在进入 音频播放页面的时候通过 this.curentMusicUrl = this.$parent.globalData.musicUrl就可以获取到了,然后在赋给这个 currentMusicUrl 变量,在把变量赋值给src音频就可以正常播放了。别忘了设置一个定时器保证时间正常往前走
2. 滑动slider 控制播放进度
滑动slider 可以触发两个事件,一个是滑动过程中一个是滑动结束,这里暂时用到滑动结束时间,起名sliderEnd(e), 通过 e.detail.value 可以拿到滑动的值, 这时候你需要知道这个音频的总的秒数才可以计算 滑动结束时候的播放进度,ok,拿播放总时长跟 获取播放地址的方式一样,都是存在 app.wpy 中,切换课时替换,例如我们起名为 this.CurrentMusicDuration = this.$parent.globalData.curentAllTime。然后 通过 this.CurrentMusicDuration * e.detail.value 可以获取到滑动结束的播放进度,将获取到的播放进度赋给 wx.seekBackgroundAudio中的position属性。
未解决bug
用户正常滑动滑块的时候 都是可以控制播放进度的,但是当用户将slider滑到0的位置,却不能改变这个position……我后来判断了一下 当滑到0 的时候 我给了position 一个值0.1就可以i播放,问题是解决了,但不是我想要的方式。求大神指教正确解决方式。
到目前为止,进入音频播放页面,1)关闭了全局定时器 2)拿到了当前播放时间 3)播放时间可以正常进行 4)滑动slider时候可以控制播放进度。至于播放和暂停之类的操作我就不解释了。下面说一说 当用户离开这个页面 和在进入的情况
如果不做其他操作,直接离开页面 然后在进入会造成两种情况,第一你的播放进度不对,你忘了我让你在onshow里面写了一个this.$parent.stopParentTime() 方法返回播放时间的么? 所以你如果在离开页面不把播放进度再次传给 全局变量,那么你下次进来的时候拿到的播放进度还是上次进来的,而你听到的声音跟进度完全不符合
第二就是你的定时器增加了,你播放的进度会增快,这么说吧,你要是不清楚你进来的次数越多 播放进度速度越快。
所以我们就要在 离开 播放页面的时候 将播放进度回传给全局,并且销毁当前组件中的定时器,通过 this.$parent.getCrentTime(time) 和 clearInterval(this.timer) 就ok了。

### 实现刮刮乐效果 要在 Wepy 框架中实现刮刮乐效果,主要思路是通过 Canvas 组件来绘制遮罩层,并允许用户通过触摸操作擦除部分区域显示下方的内容。具体来说: #### 1. 创建 Canvas 组件并绑定事件处理函数 首先,在页面的 `wxml` 文件里定义一个 `<canvas>` 标签用于绘图,并设置其宽高属性以及 id 属性以便后续 JavaScript 中获取该 canvas 对象。 ```html <view class="scratch-card"> <canvas type="2d" bindtouchstart="handleTouchStart" bindtouchmove="handleTouchMove" id="scratchCanvas"></canvas> </view> ``` #### 2. 初始化画布与背景图片加载 接着,在对应的 `.js` 文件内初始化画布上下文对象 ctx 和一些必要的变量如 scratchWidth, scratchHeight 表示可被划掉的最大宽度高度;imageSrc 存储要展示给用户的最终奖品图像路径等信息[^1]。 ```javascript import wepy from 'wepy'; export default class ScratchCard extends wepy.page { data = { imageSrc: '/static/images/prize.png', // 奖励图片资源地址 scratchWidth: 0, scratchHeight: 0, isScratchable: true }; async onLoad() { const query = wx.createSelectorQuery().in(this); await new Promise((resolve) => { query.select('#scratchCanvas').fields({ node: true }, (res) => { this.ctx = res.node.getContext('2d'); resolve(); }).exec(); }); // 加载完成后的回调函数 const img = await new Promise((resolveImg) => { const tempImage = new Image(); tempImage.src = this.data.imageSrc; tempImage.onload = () => resolveImg(tempImage); }); this.scratchWidth = img.width * 0.8; // 设置为原图大小的80% this.scratchHeight = img.height * 0.8; // 渲染初始状态下的画面 renderInitialState.call(this); } } ``` #### 3. 定义触控逻辑及渲染方法 为了能够响应用户的滑动动作从而达到“刮开”的视觉体验,还需要编写 handleTouchStart 和 handleTouchMove 方法分别用来记录手指按下位置坐标和移动过程中更新已刮去区域的数据结构(可以是一个二维数组)。最后再调用一次 render 函数重新绘制整个场景即可显示出最新的变化情况。 ```javascript // 记录上一次接触屏幕的位置 let lastX = null; let lastY = null; function handleTouchStart(e) { if (!this.isScratchable || !lastX === null || !lastY === null) return; let touch = e.touches[0]; lastX = touch.x; lastY = touch.y; } function handleTouchMove(e) { if (!this.isScratchable) return; let touch = e.touches[0]; drawLine(lastX, lastY, touch.x, touch.y); lastX = touch.x; lastY = touch.y; } function drawLine(fromX, fromY, toX, toY){ this.ctx.beginPath(); this.ctx.moveTo(fromX, fromY); this.ctx.lineTo(toX, toY); this.ctx.lineWidth = 50; this.ctx.strokeStyle = '#FFFFFF'; this.ctx.stroke(); checkIfFullyRevealed(); // 判断是否已经完全揭开 } function checkIfFullyRevealed(){ /* 这里的逻辑可以根据实际需求调整 */ console.log("Checking..."); } ``` #### 4. 添加样式美化界面布局 为了让用户体验更好一点,可以在 CSS 文件里面加入适当的选择器规则使卡片看起来更美观大方些。 ```css page{ background-color:#f7f7f7; } .scratch-card{ position:relative; width:90%; height:auto; margin-left:auto; margin-right:auto; border-radius:.2rem; overflow:hidden; box-shadow:0px 0px .5em rgba(0,0,0,.1); } #scratchCanvas{ display:block; width:100%; height:100%; } ```
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值