700字范文,内容丰富有趣,生活中的好帮手!
700字范文 > 微信小程序实现自定义音乐播放(定时 进度条)

微信小程序实现自定义音乐播放(定时 进度条)

时间:2023-06-04 09:52:04

相关推荐

微信小程序实现自定义音乐播放(定时 进度条)

实现关键:

1、wx.getBackgroundAudioManager()

2、在app.json中配置:"requiredBackgroundModes": ["audio"]

界面

具体实现步骤:

======****进度条组件

wxml

<view class="circle_box" style="{{size}}px;height:{{size}}px"><!-- <canvas class="circle_bg" canvas-id="{{draw}}bg" style="{{size + 10}}px;height:{{size + 10}}px"></canvas> --><canvas class="circle_draw" canvas-id="{{draw}}" style="{{size }}px;height:{{size }}px"></canvas> <!-- <text class='circle_txt'> {{txt}}% </text> --></view>

wxss

.circle_box,.circle_draw{ width: 100%;top: 50%;left:50%;transform: translate(-50%,-50%);position: absolute; }.circle_bg{width: 100%;top: 50%;left:50%;transform: translate(-50%,-50%);position: absolute;}.circle_box{top: 50%;left:50%;transform: translate(-50%,-50%);display: flex;flex-direction: row;justify-content: center;align-items: center;position: absolute;width: 100%;z-index: 1001;}.circle_txt{position: absolute;font-size: 28rpx;}

js

Component({options: {multipleSlots: true // 在组件定义时的选项中启用多slot支持},properties: {draw: {//画板元素名称idtype: String,value: 'draw'},per: { //百分比 通过此值转换成steptype: String,value: '0'},r: {//半径type: String,value: '50'}},observers: {"per": function (val) {// this.attached()this.init()}},data: { /* 私有数据,可用于模版渲染 */step: 1, //用来算圆的弧度0-2size: 0, //画板大小screenWidth: 750, //实际设备的宽度txt: 0},methods: {// 初始化init() {const _this = this;//获取屏幕宽度wx.getSystemInfo({success: function (res) {_this.setData({screenWidth: res.windowWidth});},});//初始化const el = _this.data.draw; //画板元素const per = _this.data.per; //圆形进度const r = Number(_this.data.r); //圆形半径_this.setData({step: (2 * Number(_this.data.per)) / 100,txt: _this.data.per});//获取屏幕宽度(并把真正的半径px转成rpx)let rpx = (_this.data.screenWidth / 750) * r;//计算出画板大小this.setData({size: rpx * 2});const w = 4;//圆形的宽度// console.log("step", _this.data.step)//组件入口,调用下面即可绘制 背景圆环和彩色圆环。_this.drawCircleBg(el + 'bg', rpx, w);//绘制 背景圆环_this.drawCircle(el, rpx, w, _this.data.step);//绘制 彩色圆环},/*** el:画圆的元素* r:圆的半径* w:圆的宽度* 功能:画背景*/drawCircleBg: function (el, r, w) {const ctx = wx.createCanvasContext(el, this);ctx.setLineWidth(w);// 设置圆环的宽度ctx.setStrokeStyle('#E5E5E5'); // 设置圆环的颜色ctx.setLineCap('round') // 设置圆环端点的形状ctx.beginPath();//开始一个新的路径ctx.arc(r, r, r - w, 0, 2 * Math.PI, false);//设置一个原点(110,110),半径为100的圆的路径到当前路径ctx.stroke();//对当前路径进行描边ctx.draw();},/*** el:画圆的元素* r:圆的半径* w:圆的宽度* step:圆的弧度 (0-2)* 功能:彩色圆环*/drawCircle: function (el, r, w, step) {var context = wx.createCanvasContext(el, this);// 设置渐变var gradient = context.createLinearGradient(2 * r, r, 0);gradient.addColorStop("0", "#F1CAAD");gradient.addColorStop("0.5", "#F1CAAD");gradient.addColorStop("1.0", "#F1CAAD");context.setLineWidth(w);context.setStrokeStyle(gradient);context.setLineCap('round')context.beginPath();//开始一个新的路径// step 从0到2为一周context.arc(r, r, r - w, -Math.PI / 2, step * Math.PI - Math.PI / 2, false);context.stroke();//对当前路径进行描边context.draw()}},lifetimes: {// 生命周期函数,可以为函数,或一个在methods段中定义的方法名attached: function () {this.init()}}})

json

{"component": true,"usingComponents": {}}

======****调用部分

wxml

<view class="playBox"><circle draw='circwewle1' class="mycanvas" per="{{ percentage }}" r='242' /><image mode="aspectFill" class="playbg {{isPlay&&'disc-animate'}}" src="{{ detailObj.playerdiagram }}"></image><image mode="aspectFill"src="{{ isPlay ? 'https://laikangland-dev.oss-cn-/09081030199l40.png?Expires=2293324220&OSSAccessKeyId=LTAIykCrXSP1fmei&Signature=Tc7RjNRt7VnPQdFxPgtob76AVE0%3D' : 'https://laikangland-dev.oss-cn-/0908103053X31u.png?Expires=2293324253&OSSAccessKeyId=LTAIykCrXSP1fmei&Signature=eIFRbPEqzCCtptvNtb3Y3VJER%2Bg%3D' }}"data-src="{{ detailObj.resUrl }}" class="play" catchtap="playMusic"></image></view>

less

.playBox {width: 484rpx;display: flex;align-items: center;justify-content: center;height: 484rpx;border-radius: 50%;margin-bottom: 140rpx;position: relative;// overflow: hidden;// border: 8rpx solid #F1CAAD;.playbg {width: 475rpx;height: 475rpx;// top: 50%;// left: 50%;position: absolute;transform: rotate(0deg)// translate(-50%,-50%)}.disc-animate {animation: rotate 3s 0s linear infinite;}.play {width: 96rpx;height: 96rpx;z-index: 1002;border-radius: 50%;}}

json

{"usingComponents": {"circle": "/components/circle/circle"},"navigationStyle":"custom"}

js

1、在onLoad中创建播放对象

data: {detailObj: null,tabIndex: null,tab: [15, 30, 60, 90, 120],isPlay: false,//是否播放countdown: null, //倒计时percentage: null //当前进度},onLoad(options) {let platform;wx.getSystemInfo({success: function (res) {platform = res.platform}});this.platform = platformlet detailObj = JSON.parse(decodeURIComponent(options.item))this.data.audioCtx = wx.getBackgroundAudioManager()this.data.audioCtx.title = detailObj.namethis.setData({ customTopHeiht: app.globalData.customTopHeiht, detailObj, showTip: detailObj.announcements ? true : false })// 创建播放对象this.createPlay()},onShow() {// this.createPlay()if (wx.getStorageSync("nowTime")) {this.newTime = wx.getStorageSync("nowTime")let tabIndex = Number(wx.getStorageSync("tabIndex"))this.setData({ tabIndex })this.countDown(this.data.tab[tabIndex])}else {this.setData({ tabIndex: null })}if(wx.getStorageSync("fmtCurrentTime")) {this.fmtCurrentTime = wx.getStorageSync("fmtCurrentTime")}},

2、将播放的步骤封装成一个方法

注意事项:

1、代码中的src为需要播放的地址

2、为了防止中文的地址在ios中无法播放,需要对其通过encodeURIComponent进行转码处理

3、必须设置title,否则无法播放

// 创建播放音乐对象createPlay() {let src = this.data.detailObj.resUrlsrc = src.indexOf('ai-algorithm-nlp') >= 0 ? src.slice(0, src.indexOf('ai-algorithm-nlp') + 6) + encodeURIComponent(src.slice(src.indexOf('ai-algorithm-nlp') + 6)) : src;this.data.audioCtx.src = srcif (app.globalData.tabIndex || app.globalData.tabIndex == 0) {this.setData({ isPlay: true, tabIndex: app.globalData.tabIndex })}if(wx.getStorageSync('nowTime') && (this.data.countdown&&this.data.countdown.sec <= 0)) {this.setData({ tabIndex: null })this.data.audioCtx.stop()}else {setTimeout(() => {this.data.audioCtx.play()}, 300)}// 监听音乐播放this.data.audioCtx.onPlay(() => {this.handleList(true)this.setData({ isPlay: true })})// 监听音乐暂停this.data.audioCtx.onPause(() => {this.handleList(false)this.setData({ isPlay: false })})// 监听音乐停止this.data.audioCtx.onStop(() => {this.handleList(false)this.setData({ isPlay: false })})// 监听音乐结束this.data.audioCtx.onEnded(() => {console.log("音乐结束")// 循环播放this.data.audioCtx.pause()this.data.audioCtx.play()})// 监听播放进度this.data.audioCtx.onTimeUpdate(() => {let fmtCurrentTime = this.fmtCurrentTime ? this.fmtCurrentTime : moment(this.data.audioCtx.currentTime * 1000).format("mm");let tabIndex = this.data.tabIndexlet time = this.data.tab[tabIndex]app.globalData.tabIndex = tabIndexwx.setStorageSync("fmtCurrentTime",fmtCurrentTime)let percentage = (this.data.audioCtx.currentTime/this.data.audioCtx.duration)*100this.setData({ percentage: percentage+''})// console.log("percentage",percentage)if(this.fmtCurrentTime && wx.getStorageSync('nowTime') && this.data.countdown) {if (Number(this.data.countdown.sec) <= 0) {// 定时结束console.log("定时结束")this.setData({ isPlay: false,tabIndex: null })this.data.audioCtx.stop()}}else {if (wx.getStorageSync('nowTime')&&Number(fmtCurrentTime) >= time) {// 定时结束console.log("定时结束")this.setData({ isPlay: false,tabIndex: null })this.data.audioCtx.stop()}}})if (this.data.detailObj.isPlay) {this.data.audioCtx.src = this.data.detailObj.resUrl// this.data.audioCtx.pause()this.data.audioCtx.play()this.setData({ isPlay: true })}},

3、处理播放按钮点击时对应的事件

// 播放音乐playMusic(e) {this.setData({ isPlay: !this.data.isPlay })// let src = e.currentTarget.dataset.src// src = src.indexOf('ai-algorithm-nlp') >= 0 ? src.slice(0,src.indexOf('ai-algorithm-nlp')+6) + encodeURIComponent(src.slice(src.indexOf('ai-algorithm-nlp') + 6 )) : src;// this.data.audioCtx.src = src// this.data.audioCtx.src = '/68514b723d30472ba691c9b91b529631/4b8b9e29983c41848d01e173a115bc68-a186ac753c224d0a3647598c3ba3aab6-ld.mp4'if (this.data.isPlay) {this.data.audioCtx.pause()this.data.audioCtx.play()} else {this.setData({ isPlay: false })this.data.audioCtx.pause()}},

4、处理定时弹框关闭对应事件

know() {if (this.data.isWho != 1) {clearInterval(this.data.timer)this.setData({ countdown: null })this.newTime = moment(new Date()).format('YYYY-MM-DD HH:mm:ss')wx.setStorageSync("nowTime", this.newTime); //定时wx.setStorageSync("tabIndex", this.data.tabIndex);this.countDown(this.data.tab[this.data.tabIndex])}this.setData({ isWho: null })},

4、处理定时时间切换事件

change(e) {let tabIndex = e.currentTarget.dataset.indexapp.globalData.tabIndex = tabIndexthis.setData({ tabIndex })},

5、处理定时器以及倒计时回显

countDown: function (time) {let that = this,countdown = this.data.countdown// let num = 0;clearInterval(this.data.timer)that.data.timer = setInterval(function () {let createdTime = that.newTimeif (that.platform == 'ios') {createdTime = createdTime.replace(/-/g, '/')}// 30分钟-半小时let lastTime = new Date(new Date(createdTime).getTime() + (1 / 60) * time * 3600 * 1000)let nowTime = new Date()let flag = pareDate(lastTime,nowTime)if (flag > 0) {countdown = that.myFunction(nowTime,lastTime)} else {countdown = null// 定时结束清除定时时间wx.removeStorageSync("fmtCurrentTime")wx.removeStorageSync('nowTime')wx.removeStorageSync('tabIndex')clearInterval(that.data.timer)}that.setData({ countdown })}, 1000)},myFunction(startDate, endDate) {let min = Math.floor((new Date(endDate).getTime() - new Date(startDate).getTime()) / 60000)let sec = Math.floor((new Date(endDate).getTime() - new Date(startDate).getTime()) / 1000)let tmp = min <= 0 ? sec : sec%60 >= 0 ?sec%60 : seclet str = min > 0 ? `${min}:${ tmp }` : `${min}:${sec }`return { str,sec }},// 比较两个日期的小compareDate(date1, date2) {let tmp1 = date1.getTime();let tmp2 = date2.getTime();return tmp1 - tmp2},

本内容不代表本网观点和政治立场,如有侵犯你的权益请联系我们处理。
网友评论
网友评论仅供其表达个人看法,并不表明网站立场。