Loading [MathJax]/jax/output/CommonHTML/config.js
前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
社区首页 >专栏 >微信小程序-音乐播放器+背景播放

微信小程序-音乐播放器+背景播放

作者头像
super.x
发布于 2019-11-03 04:40:41
发布于 2019-11-03 04:40:41
10K20
代码可运行
举报
运行总次数:0
代码可运行
需求描述:

1.正常播放音频 2.可以滑动进度条 3.可以切换上一条,下一条音频 4.退出当前页或关闭小程序之后仍然可以正常播放 5.试听功能进入该播放页不可以播放上一条,下一条 6.退出该页面或小程序之后,再次回到该页面,播放条自动到当前播放进度

图二图三是关闭小程序之后微信页面的展示,可以通过悬浮关闭该音频。

参考文档 [小程序官方文档--背景音频]

⚠️ 使用小程序 BackgroundAudioManager,需要在 app.json配置相关参数

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
"requiredBackgroundModes": [
    "audio"
  ]
代码
代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
    <view class="vp-book-adPlayer">
        <view class="adp-wrapper">
            <view class="apd-progress">
                <!-- <audio class="apd-pro-audio" src="{{music.src}}" action="{{audioAction}}" bindplay="audioPlayed" bindtimeupdate="audioTimeUpdated" controls></audio> -->
                <!-- 之前用的是audio标签,但是为了能够满足退出当前页面或者关闭小程序,音频仍需播放的需求,改成了背景音频-->
                <slider class="apd-pro-slider" value="{{slideLen}}" bindchanging="stopSlider" bindchange="timeSliderChanged" selected-color="#20a3ff" block-size="12" block-color="#20a3ff" step="0.01"/>
                <view class="apd-pro-timer">
                    <view class="apd-pro-start">{{music.start}}</view>
                    <view class="apd-pro-leave">{{music.leave}}</view>
                </view>
            </view>
            <view class="apd-btn-box">
                <!-- 列表图标-->
                <image class="apd-btn-list" src="../../img/player/ico-list.png" bindtap="jumpAudioList"></image>
                <!-- 上一条图标-->
                <image class="{{hasPre ? 'apd-btn-left' : 'apd-btn-left apd-btn-no'}}" bindtap="playPer" src="../../img/player/ico-left.png"></image>
                <!-- 暂停和播放图标-->
                <image class="apd-btn-player" bindtap="ppAudio" src="{{isPlay ? '../../img/player/ico-pause.png' : '../../img/player/ico-player.png'}}"></image>
                <!-- 下一条图标-->
                <image class="{{hasNxt ? 'apd-btn-right' : 'apd-btn-right apd-btn-no'}}" bindtap="playNxt" src="../../img/player/ico-right.png"></image>
            </view>
        </view>
    </view>
    
    
    
    // pages/audioPlayer/audioPlayer.js
const api = require('../../service/http.js');
const util = require('../../utils/util.js')
var App = getApp()
const bgMusic = App.bgMusic  //创建背景音乐
Page({
  /**
   * 页面的初始数据
   */
  data: {
    isTry: null,  // 是否是试听状态
    idx: 0, // 当前音频(第一个-上一条按钮不能点击,最后一条,下一条按钮不能点击)
    albumCode: '',  // 当前音频标识
    opusName: '',  // 当前专辑名字
    musicSrc: '',  
    singler: '',  // 当前作者
    audioMsg: {},  // 音频信息(作者,封面,名字--仅展示)
    opusSalt: '',  // 当前音频id
    isEnd: false, // 最后一条音频结束时控制
    endVideoTime: '', // 最后一条音频时长
    isPlay: true,  // 是否暂停音乐
    isStop: false,  // 是否停止音乐
    slideLen: 0, // 进度条初始值
    music: {  // 音频信息--用来处理数据
      start: '00:00',
      leave:'',
      long: '',
      length: ''
    },
    hasPre: true,  // 是否有上一条音频
    hasNxt: true,  // 是否有下一条音频
    musicList: [], // 用来存储音频列表,存储到本地,点击上一条、下一条音频时,不调用接口
    perMusicMsg: {},  // 进入页面之后,就将上一条音频,下一条音频信息提取出来,方便直接点击按钮
    nxtMusicMsg: {},  // 同上
    isStopSlider: false  // 是否停止滚动条随着音频播放改变长度  -- 防止拖动滚动条时发生回退现象!!!
  },

  /**
   * 生命周期函数--监听页面加载
   */
  onLoad: function (options) {
    let book
    try {
      let value = wx.getStorageSync('ai_cloud_book')
      if (value) {
        book = JSON.parse(value)
      }
    } catch (e) {
      // Do something when catch error
    }
    this.setData({
      albumCode: decodeURIComponent(options.albumCode),
      musicSrc: decodeURIComponent(options.playerUrl),
      opusName: decodeURIComponent(options.playerName),
      singler: decodeURIComponent(options.playerSinger),
      isTry: Boolean(Number(options.isTry)),
      audioMsg: book,
      opusSalt: options.opusSalt,
      idx: Number(options.idx),
      'music.long': util.formatM(options.playerLong),
      'music.length': options.playerLong,
    })
  },

  /**
   * 生命周期函数--监听页面初次渲染完成
   */
  onReady: function () {
    // 正在播放-进入(重新进入当前页面时)
    // this.data.opusSalt === App.globalData.opusSalt  判断从列表进入时,想要播放的和正在播放的是否为同一条音频
    if(bgMusic.src && this.data.opusSalt === App.globalData.opusSalt) {
      this.audioInitAgain()
    } else {
      // 进入的和之前播放的不是同一条音频  存储将要播放的音频id,并获取将要播放的音频数据,然后播放
      App.globalData.opusSalt = this.data.opusSalt
      this.getAudioSrc()
    }
    // 试听只能听第一条,上一条,下一条按钮不可点击
    if(this.data.isTry) {
      this.setData({
        hasPre: false,
        hasNxt: false
      })
    } else {
      this.musicListHandle()
    }
  },

  // 跳转专辑列表-- 返回上一页面
  jumpAudioList: function() {
    wx.navigateBack()
  },
  // 获取音频信息
  getAudioSrc: function() {
    bgMusic.src = this.properties.musicSrc
    bgMusic.title = this.data.opusName
    bgMusic.epname = this.data.opusName
    bgMusic.singer = this.data.singer
    // 最后一条音乐存储一下音乐时长--- 播放结束后,不自动跳转下一条音频,播放按钮变为暂停,滚动条置0,endVideoTime展示该音频时长
    this.setData({
      endVideoTime: this.data.music.long
    })
    this.audioInitPlay()
  },
  // 音频-暂停/播放
  // isPlay: true: 播放状态  false:暂停状态
  // isStop:true :当不在播放页面时,点击关闭悬浮框的关闭按钮  false: 悬浮框未关闭  --- 实际监听时,监听不到悬浮框关闭,但依然保留了该字段
  ppAudio: function (e) {
    let _isPlay = this.data.isPlay
    let _isStop = this.data.isStop
    if(_isStop) {
      this.getAudioSrc()
      this.setData({
        isPlay: true,
        isStop: false
      })
      return
    }
    if(_isPlay) {
      this.pauseAudio()
    } else if(this.data.isEnd){
      // 最后一条音频 - 再次播放需要重新初始化
      this.setData({
        isEnd: false
      })
      this.getAudioSrc()
    } else {
      this.playAudio()
    }
    this.setData({
      isPlay: !_isPlay
    })
  },
  // 音频实时信息  -->  
  audioTimeUpdated: function (e) {
    const startTime = e.currentTime
    const leaveTime = e.duration - startTime
    this.setData({
      "music.start": util.formatM(startTime),
      "music.leave": util.formatM(leaveTime)
    })
    if(!this.data.isStopSlider) {
      const proLen = (e.currentTime / e.duration * 100).toFixed(2)
      this.setData({
        slideLen: proLen
      })
    }
  },
  /**
   * !!! 解决滑动播放条时的卡顿问题 !!! --- start
   */
  // 禁止播放条随着音乐播放滚动
  stopSlider: function () {
    this.setData({
      isStopSlider: true
    })
  },
  // 音频播放条改变 - 手动滑动滚动条停止
  timeSliderChanged: function (e) {
    this.setData({
      isStopSlider: false
    })
    if (!this.data.music.length)
      return;

    var time = this.data.music.length * e.detail.value / 100;

    // 音频跳转到指定位置
    bgMusic.seek(time)
  },
  /**
   * !!! 解决滑动播放条时的卡顿问题  --- end
   */
  // 开始播放-首次进入
  audioInitPlay: function () {
    App.globalData.opusSalt = this.data.opusSalt

    //监听音乐自然播放结束
    bgMusic.onEnded(() => {  
      // 如果没有下一个直接赋值并禁止播放
      if(!this.data.hasNxt) {
        let _endTime = this.data.endVideoTime
        let idx = 0
        let _timer = setInterval(()=>{
          if(idx > 1) {
            clearInterval(_timer)
          }
          this.setData({
            isPlay: false,
            isEnd: true,
            "music.start": "00:00",
            "music.leave": _endTime
          })
          console.log(this.data.music)
          idx ++
        }, 50)
      } else {
        this.playNxt()
      }
    })

    //监听音乐播放
    bgMusic.onPlay(() => {
      console.log('onPlay')
      if(this.data.music.start == "00:00") {
        this.setData({
          "music.leave": util.formatM(bgMusic.duration),
          isPlay: true
        })
      }
      this.playAudio()
    })

    // 监听背景音频暂停事件
    bgMusic.onPause(() => {
      this.setData({
        isPlay: false
      })
      // App.globalData.opusSalt = 0
    })

    //监听背景音频停止事件  --- 实际监听时,监听不到悬浮框关闭,但依然保留了该字段
    bgMusic.onStop(() => {
      this.stopAudio()
      App.globalData.opusSalt = 0
    })
  },
  // 开始播放-重复进入
  audioInitAgain: function() {
    // true - 暂停中  false - 播放中
    this.setData({
      endVideoTime: util.formatM(bgMusic.duration)
    })
    console.log(this.data.endVideoTime)
    if(bgMusic.paused) {
      bgMusic.play()
      let timer = setTimeout(() => {
        clearTimeout(timer)
        //监听音乐播放
        bgMusic.onPlay(() => {
          this.playAudio()
        })
      }, 30)
    } else {
      bgMusic.onTimeUpdate(() => {
        this.audioTimeUpdated(bgMusic)
      })
    }
  },
  //暂停
  pauseAudio: function () {
    bgMusic.pause(); 
  },
  // 继续播放
  playAudio: function () {
    // 监听音频播放进度
    bgMusic.onTimeUpdate(() => {  
      this.audioTimeUpdated(bgMusic)
    })
    bgMusic.play() //播放音乐
  },
  // 背景音乐浮窗关闭,重置数据  -- 实际监听不到悬浮框关闭事件
  stopAudio: function() {
    this.setData({
      isStop: true,
      isPlay: false,
      "music.start": "00:00",
      "music.leave": this.data.music.long,
      slideLen: 0
    })
  },
  // 上一首
  playPer() {
    if(!this.data.hasPre) return
    wx.redirectTo({
      url: `XX/audioPlayer?albumCode=${encodeURIComponent(this.data.albumCode)}&playerUrl=${encodeURIComponent(this.data.perMusicMsg.opusUrl)}&playerName=${encodeURIComponent(this.data.perMusicMsg.opusName)}&playerSinger=${encodeURIComponent(this.data.singer)}&playerLong=${this.data.perMusicMsg.opusLength}&opusSalt=${this.data.perMusicMsg.opusSalt}&idx=${this.data.idx - 1}&isTry=0`
    })
  },
  // 下一首
  playNxt() {
    if(!this.data.hasNxt) return
    wx.redirectTo({
      url: `XXX/audioPlayer?albumCode=${encodeURIComponent(this.data.albumCode)}&playerUrl=${encodeURIComponent(this.data.nxtMusicMsg.opusUrl)}&playerName=${encodeURIComponent(this.data.nxtMusicMsg.opusName)}&playerSinger=${encodeURIComponent(this.data.singer)}&playerLong=${this.data.nxtMusicMsg.opusLength}&opusSalt=${this.data.nxtMusicMsg.opusSalt}&idx=${this.data.idx + 1}&isTry=0`
    })
  },
  // 音乐数据处理
  musicListHandle() {
    try {
      let value = wx.getStorageSync('ai_cloud_book_album')
      if (value) {
        let _book = JSON.parse(value)
        let _hasPer = Boolean(this.data.idx)  
        let _hasNxt = this.data.idx === _book.length - 1 ? 0 : 1
        let _perMusicMsg = {}
        let _nxtMusicMsg = {}
        if(_hasPer) _perMusicMsg = _book[this.data.idx - 1]
        if(Boolean(_hasNxt)) _nxtMusicMsg = _book[this.data.idx + 1]
        this.setData({
          musicList: _book,
          hasPre: _hasPer,
          hasNxt: Boolean(_hasNxt),
          perMusicMsg: _perMusicMsg,
          nxtMusicMsg: _nxtMusicMsg
        })
      }
    } catch (e) {
      // Do something when catch error
    }
    // wx.setStorageSync("ai_cloud_book_album", JSON.stringify(this.data.listenList))
  }
})

音频-暂停/播放(信息配置) ppAudio() 音频实时信息 audioTimeUpdated() 音频播放条改变 timeSliderChanged() 开始播放-首次进入 audioInitPlay() 开始播放-重复进入 audioInitAgain() 暂停 pauseAudio() 继续播放 playAudio()

函数作用都已经在注释里标注了,有疑问的地方欢迎留言~~

本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
2 条评论
热度
最新
老哥 你好 有源码么
老哥 你好 有源码么
回复回复点赞举报
大佬,我用背景音频,为啥没有悬浮框啊
大佬,我用背景音频,为啥没有悬浮框啊
回复回复点赞举报
推荐阅读
编辑精选文章
换一批
微信小程序音乐播放器组件
若本号内容有做得不到位的地方(比如:涉及版权或其他问题),请及时联系我们进行整改即可,会在第一时间进行处理。----
达达前端
2019/08/23
2.7K2
html+原生js制作一个简易音乐播放器
下面这些按钮是导入了字体图标库font-awesome 4.7.0 ,需要自己引入
用户10604450
2024/03/15
1670
html+原生js制作一个简易音乐播放器
【愚公系列】《微信小程序与云开发从入门到实践》024-开发音乐播放器软件
在数字音乐盛行的今天,音乐播放器成为了人们日常生活中不可或缺的一部分。微信小程序以其轻便、便捷的特性,成为开发音乐播放器的理想选择。通过小程序,用户可以随时随地享受高品质的音乐体验,而开发者则能够利用微信平台的丰富生态,快速构建和推广自己的音乐应用。
愚公搬代码
2025/01/18
1110
微信小程序创建BackgroundAudioManager实例,播放背景音频
打不着的大喇叭
2024/03/11
5810
【愚公系列】2022年03月 微信小程序-音频文件
文章目录 前言 一、音频文件 1.旧版 2.新版 ---- 前言 audio 属性 类型 默认值 必填 说明 最低版本 id string 否 audio 组件的唯一标识符 1.0.0 src string 否 要播放音频的资源地址 1.0.0 loop boolean false 否 是否循环播放 1.0.0 controls boolean false 否 是否显示默认控件 1.0.0 poster string 否 默认控件上的音频封面的图片资源地址,如果 controls 属性值为 false
愚公搬代码
2022/12/01
5980
【愚公系列】2022年03月 微信小程序-音频文件
微信小程序中将图片与音乐制作成MV
最近一直在开发一个类似于小年糕的微信小程序,在开发制作MV功能时 ,花费了一些心思,其间主要遇到了以下一些问题点:
越陌度阡
2020/11/26
2.1K0
微信小程序中将图片与音乐制作成MV
八、jQuery的QQ音乐播放器
自定义滚动条使用了一个jQuery插件jQuery custom content scroller。利用这个插件可以轻松设置滚动条样式。
Dreamy.TZK
2020/06/22
4.4K0
实验三 音乐播放器
1、掌握服务的基本概念,能编写服务过程并进行调用; 2、掌握广播的基本概念,能实现广播通信。 3、需实现的具体功能为: 短信到来时自动产生的系统广播→激活音乐播放服务程序→活动组件程序使得停止按钮可用。 实现思路 • MainActivity启动服务,将播放、暂停、停止、切换信号发送广播给Service • MusicService 调用函数Prepareandplay()播放音乐,发送广播给MainActivity返回歌曲id • PrepareAndPlay() 定向操作 打开并播放音乐文件 注意的点 • 记得在配置文件中注册服务 • 注意findViewById在Fragment的使用方法 • 在Fragment中给ImageButton绑定事件监听器要重写onActivityCreated方法
twelvecoder
2021/12/24
1.5K0
实验三 音乐播放器
小程序添加背景音乐,避开了深坑,记录实现方法
简介 小程序背景音乐,看着官方文档实现,难免会遇到这样那样的坑,例如切换页面,音乐重头播放。如何实现手动暂停、播放。下面就介绍了如何简单实现背景音乐播放。
子润先生
2021/06/25
1.3K0
Android 多媒体开发学习之简单的音乐播放器
我们今天的目的是学习如何创建一个简单的音乐播放器,可支持播放,暂停,继续播放,以及进度显示,已经进度拖拽。
DragonKingZhu
2022/05/08
7140
Android 多媒体开发学习之简单的音乐播放器
Android应用界面开发——BroadcastReceiver(实现基于Service的音乐播放器)
BroadcastReceiver用于接收程序(开发者开发的程序和系统程序)发出的Broadcast Intent,程序启动BroadcastReceiver需要两步:
trampcr
2018/09/28
1.6K0
Android应用界面开发——BroadcastReceiver(实现基于Service的音乐播放器)
HTML5+Ajax实现音乐播放器
播放器的音乐是通过豆瓣FM的API获取到的,我们可以随机的听到豆瓣FM的任何音乐。(这些API是饥人谷的老师整理的),音乐播放器美观如图:
用户1093975
2018/08/02
9.3K2
HTML5+Ajax实现音乐播放器
微信小程序录音与音频播放控制功能
  小程序继承了微信强大的语音处理功能,提供了录音、音频播放控制和背景音乐等功能,它们的功能不同,但有相似性。
别团等shy哥发育
2023/02/25
4.9K0
微信小程序录音与音频播放控制功能
replay视频播放器_怎么让手机音乐跟视频一起放
1.AVPlayer (负责视频操作,例如播放,暂停,声音的大小,跳到指定的时间)
全栈程序员站长
2022/08/02
1.4K0
基于 Android Studio 音乐播放器App
点击右侧文字传送:基于 Android Studio 实现的简易 音乐播放器App_android studio音乐播放器-CSDN博客
编程乐学
2024/07/01
1900
基于 Android Studio  音乐播放器App
Android实现背景音乐播放
实现这个功能将用到android的四大组件之一:Service 注意:Service是自大组件之一,需要注册。
程思扬
2022/01/11
1.3K0
Android实现背景音乐播放
微信小程序实战–集阅读与电影于一体的小程序项目(三)
在文章详情页,点击播放音乐后,然后返回到文章列表页,再进到详情页,发现播放按钮是暂停状态,这是因为应用程序存在生命周期,下面就解决这个问题。
zhang_derek
2018/08/30
9410
微信小程序实战–集阅读与电影于一体的小程序项目(三)
微信小程序开发实战(29):控制背景音乐
小程序还提供一组用于播放背景音乐的API,背景音乐和普通音乐的区别就是背景音乐在当前页面播放后,即使切换到当前小程序的其他页面,也不会停止播放。但当小程序退出后,背景音乐就会停止播放。
蒙娜丽宁
2020/09/07
2.7K0
微信小程序开发实战(29):控制背景音乐
HTML简单音乐播放器「建议收藏」
通过JS部分的代码,动态给歌曲信息模块(id为player-content1)的DOM元素添加/移除active类名。 设置CSS3动画过渡属性: transition:top 0.3s ease;来生成过渡时间0.3s,速度逐渐变慢的: 上移动画效果:top:0px; ——>top:-85px; 下移动画效果: top:-85px; ——>top:0px;
全栈程序员站长
2022/09/07
4.3K0
用Python写一个“听后即焚”的极简音乐播放器
这个极极极简的音乐播放器类似于“阅后即焚”的软件,播放器可以随机播放歌曲,获取下一首歌曲,不能重新播放上一首歌曲,不能获取歌曲的名称和演唱者。听过的歌曲,就像过眼云烟,放完即散。
州的先生
2020/02/14
1.9K0
用Python写一个“听后即焚”的极简音乐播放器
推荐阅读
相关推荐
微信小程序音乐播放器组件
更多 >
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档
查看详情【社区公告】 技术创作特训营有奖征文
本文部分代码块支持一键运行,欢迎体验
本文部分代码块支持一键运行,欢迎体验