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

这篇具有很好参考价值的文章主要介绍了微信小程序实现自定义音乐播放(定时、进度条)。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

实现关键:

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: {//画板元素名称id
      type: String,
      value: 'draw'
    },
    per: { //百分比 通过此值转换成step
      type: String,
      value: '0'
    },
    r: {//半径
      type: String,
      value: '50'
    }

  },

  observers: {
    "per": function (val) {
      // this.attached()
      this.init()
    }
  },

  data: { /*  私有数据,可用于模版渲染 */
    step: 1, //用来算圆的弧度0-2
    size: 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-beijing.aliyuncs.com/202209081030199l40.png?Expires=2293324220&OSSAccessKeyId=LTAIykCrXSP1fmei&Signature=Tc7RjNRt7VnPQdFxPgtob76AVE0%3D' : 'https://laikangland-dev.oss-cn-beijing.aliyuncs.com/20220908103053X31u.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 = platform
        let detailObj = JSON.parse(decodeURIComponent(options.item))
        this.data.audioCtx = wx.getBackgroundAudioManager()
        this.data.audioCtx.title = detailObj.name
        this.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.resUrl
        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
        if (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.tabIndex
            let time = this.data.tab[tabIndex]
            app.globalData.tabIndex = tabIndex
            wx.setStorageSync("fmtCurrentTime",fmtCurrentTime)
            let percentage = (this.data.audioCtx.currentTime/this.data.audioCtx.duration)*100
            this.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 = 'https://video.laikang.com/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.index
        app.globalData.tabIndex = tabIndex
        this.setData({ tabIndex })
    },

 5、处理定时器以及倒计时回显文章来源地址https://www.toymoban.com/news/detail-594700.html

 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.newTime
            if (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 = that.compareDate(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 : sec
        let str = min > 0 ? `${min}:${ tmp }` : `${min}:${sec }`
        return { str,sec }
    },

    // 比较两个日期的小
    compareDate(date1, date2) {
        let tmp1 = date1.getTime();
        let tmp2 = date2.getTime();
        return tmp1 - tmp2
    },

到了这里,关于微信小程序实现自定义音乐播放(定时、进度条)的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 案例115:基于微信小程序的音乐播放器的设计与实现

    文末获取源码 开发语言:Java 框架:SSM JDK版本:JDK1.8 数据库:mysql 5.7 开发软件:eclipse/myeclipse/idea Maven包:Maven3.5.4 小程序框架:uniapp 小程序开发软件:HBuilder X 小程序运行软件:微信开发者 目录 目录 前言 系统展示 系统首页界面的设计实现 用户注册功能的设计实现 用户登

    2024年02月02日
    浏览(43)
  • 基于微信小程序音乐播放器的设计与实现毕业设计源码271156

    Springboot音乐播放小程序的设计与实现 摘 要 本文设计了一种基于微信小程序的音乐播放器,系统为人们提供了方便快捷、即用即搜的音乐搜索播放服务,包括音乐资讯、音乐库推荐、交流论坛、注册登录、最近播放列表功能等,用户不仅能够方便快捷地查看资讯、还能搜索

    2023年04月24日
    浏览(49)
  • 基于微信小程序的音乐播放器设计与实现(源码+lw+部署文档+讲解等)

    💗 博主介绍 :✌全网粉丝10W+,CSDN特邀作者、博客专家、CSDN新星计划导师、全栈领域优质创作者,博客之星、掘金/华为云/阿里云/InfoQ等平台优质作者、专注于Java、小程序技术领域和毕业项目实战✌💗 👇🏻 精彩专栏 推荐订阅 👇🏻 2023-2024年最值得选的微信小程序毕业设

    2024年02月03日
    浏览(35)
  • 微信小程序音乐播放功能代码

    咱就是话不多说直接上代码,不让亲戚老爷们苦等。 首先,在你的小程序页面的js文件中,定义音乐播放相关的数据和方法: 然后,在你的小程序页面的wxml文件中,添加相关的按钮和状态显示: 最后,在微信开发者工具中预览或真机调试你的小程序,点击对应的按钮即可实

    2024年02月16日
    浏览(37)
  • 微信小程序--音乐播放器

    说明: 这个项目旨在练习组件以及页面的设计。页面和交互的实现可能有多种方式,这里只为了对组件和项目的结构进行熟悉了解。后续会有更加完善的项目。 由于涉及到mp3外链导入音乐,预览二维码在外链失效时会出错,这里不放预览二维码了;另预览二维码存在有效时

    2024年02月09日
    浏览(45)
  • uni-app Vue3实现一个酷炫的多功能音乐播放器支持微信小程序后台播放

    本文存在多张gif演示图,建议在 wifi 环境下阅读📖 最近在做网易云音乐微信小程序开源项目的时候,关于 播放器功能 参考了一些成熟的微信小程序,如 网易云音乐小程序 和 QQ音乐小程序 ,但是发现这些 小程序端 的播放器相对于 APP端 来说较简单,只支持一些基础功能,

    2024年01月24日
    浏览(72)
  • 音乐播放器微信小程序

    一:学习目标: 掌握swiper组件、scroll-view组件的使用; 掌握image组件的使用; 掌握slider组件的使用; 掌握音频API的使用;  二:目录: 1. 开发前的准备 1.1 音乐小程序 项目展示 : 1.1.1: 音乐推荐 界面展示: 1.1.2: 播放器 界面展示: 1.1.3: 播放列表 界面展示: 1.2: 项目

    2024年02月05日
    浏览(71)
  • 微信小程序音乐播放器实践

    1.成品展示: 实现搜索音乐,同步歌词,控制播放等功能 2.设计: 采用微信开发文档中的audio组件的作为代码原型,进行扩展,链接audio | 微信开放文档 (qq.com) 3、具体设计 思维导图 链接:https://pan.baidu.com/s/1whZC2xOP4HvbDMjMPA7pRQ  提取码:ljsb 3.1 播放界面index 3.2 索引界面list

    2024年02月11日
    浏览(42)
  • 微信小程序——【云音乐播放器】

    目录 第一章 开发准备 一、项目结构 二、新建微信小程序项目 第二章 标签页切换 一、常用组件介绍 二、编写页面结构和样式 第三章 音乐推荐 一、组件介绍 二、编写音乐推荐页面结构和样式 第四章 播放器 一、任务分析 二、组件介绍 三、实现播放器功能 四、编写播放器

    2024年02月09日
    浏览(44)
  • 《微信小程序》音乐播放器项目

    需求:在装有node.js的机器上使用微信开发者工具开发一个音乐播放项目 写这个项目的时候电脑前后蓝屏了5次,制作不易,希望大佬们给个双击,顺子在这感谢啦! 展示: pages–index–index.js 01.png 02.png 02stop.png 03.png 04.png 05.png 06.png banner.jpg banner2.jpg banner3.jpg cover.jpg cover1.png

    2024年02月11日
    浏览(50)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包