微信小程序音乐播放
最近在写一个艾美食艾音乐的微信小程序,其中有用到音乐播放的功能,基本播放切换功能已经实现,但是在反复切换歌曲、重新进入歌曲以及单曲循环、列表循环的测试过程中还是发生了bug,特此写一篇文章,捋一下思路.(功能写到后面小程序官方文档将音频这一块全都更新了...)
坑点:由于小程序主体部分没有app.wxml,这就导致小程序不能写一些公共的页面结构,如果有相同的部分,只能封装成组件再引入.
在我们点击歌曲列表中的某首歌的时候,会进入音乐播放界面,当我们退出音乐播放界面,歌曲仍然继续播放,但此时由于退出当前路由,页面data中的数据也已被销毁,当我们再次进入播放界面相当于重新进行页面加载,所以需要我们进行分情况判断,播放歌曲变的较为复杂.
一.存放公共数据
在我们进入音乐播放界面之前要存一下:
当前专辑信息:album(Object)
当前播放列表:playList(Array)
当前播放歌曲的index:playIndex(Number)
播放模式:mode(String)
封面旋转的角度:imgRotate(Number)
// app.js
globalData: {
album: null, // 当前专辑信息
playList: [], // 当前播放列表
playIndex: 0, // 当前播放歌曲index
mode: 'multiple', // 循环模式 multiple: 循环播放, single: 单曲循环
imgRotate: 0, // 封面旋转角度
}
二.专辑列表
在专辑列表中点击某个专辑,进入该专辑的歌曲列表,同时将 该专辑的信息 存入globalData.
// music.js
gotoSongList(e) {
let item = e.currentTarget.dataset.type
app.globalData.album = item // 将专辑信息存入globalData
wx.navigateTo({
url: '../songlist/songlist'
})
}
三.歌曲列表
在歌曲列表中点击播放某首歌时,进入歌曲播放界面,同时将 该专辑的歌曲列表、当前播放歌曲的index 存入globalData.
// songlist.js
// 播放歌曲
play(e) {
app.globalData.playList = this.data.songList
let index = e.currentTarget.dataset.index
app.globalData.playIndex = index
let url = '../player/player'
wx.navigateTo({
url: url
})
}
四.歌曲播放页面
需要在data中存放一下信息:
当前歌曲信息:item(Object)
歌曲解析后的歌词:parseLyric(String)
当前播放进度点的歌词:lineLyric(String)
播放模式:mode(String)
封面旋转的角度:imgRotate(Number)
进度条的值:SliderValue(Number)
音频的长度:duration(Number)
音频的播放位置:currentPosition(Number)
播放状态:playStatus(Boolean)
const app = getApp();
var Base64 = require('../../utils/base64.js').Base64
var Lyric = require('../../utils/lyric-parse.js')
Page({
data: {
item: {}, // 当前歌曲信息
parseLyric: '', // 歌曲解析后的歌词
lineLyric: '', // 当前播放进度点的歌词
mode: '', // 播放模式
imgRotate: 0, // 封面旋转的角度
sliderValue: 0, // 进度条的值
duration: 0, // 音频的长度(单位:s)
currentPosition: 0, // 音频的播放位置(单位:s)
playStatus: 0, // 播放状态
timee: 0, // 定时器 根据歌曲进度改变slider进度
coverImg: '', // 封面图片
isDel: false, // 当前列表是否只有一首歌曲
},
onLoad() {
let item = app.globalData.playList[app.globalData.playIndex]
let album = app.globalData.album
// 获取背景音频信息
const backgroundAudioManager = wx.getBackgroundAudioManager()
console.log(backgroundAudioManager, 'backgroundAudioManager')
if (backgroundAudioManager.src == item.src) { // 继续听歌
console.log('继续听歌')
} else { // 播放新歌
app.globalData.imgRotate = 0
console.log('播放新歌')
backgroundAudioManager.title = item.name
backgroundAudioManager.epname = album.name
backgroundAudioManager.singer = item.author
backgroundAudioManager.coverImgUrl = album.poster
// 设置了 src 之后会自动播放
backgroundAudioManager.src = item.src
}
let lyric = Base64.decode(item.lyric)
this.setData({
item: item,
coverImg: album.poster,
playStatus: !backgroundAudioManager.paused,
duration: this.stotime(backgroundAudioManager.duration),
currentPosition: this.stotime(backgroundAudioManager.currentTime),
parseLyric: new Lyric(lyric, this.handleLyric),
mode: app.globalData.mode,
imgRotate: app.globalData.imgRotate
})
this.data.parseLyric.seek(backgroundAudioManager.currentTime*1000)
console.log(this.data.playStatus, 'playStatus')
if (backgroundAudioManager.paused) {
this.data.parseLyric.togglePlay()
} else if (!this.data.timee) {
this.toRotate()
}
backgroundAudioManager.onPlay(this.onPlay) // 监听背景音频播放事件
backgroundAudioManager.onPause(this.onPause) // 监听背景音频暂停事件
backgroundAudioManager.onTimeUpdate(this.onTimeUpdate) // 监听背景音频播放进度更新事件
backgroundAudioManager.onEnded(this.onEnded) // 监听背景音频自然播放结束事件
wx.setNavigationBarTitle({
title: item.name
})
console.log(app.globalData.playList.length, 'app.globalData.playList.length')
if (app.globalData.playList.length == 1) {
this.setData({
isDel: true
})
}
},
handleLyric({lineNum, txt}) { // 歌词回调
console.log(lineNum, txt, 'txt')
this.setData({
lineLyric: txt
})
},
onPlay() {
const backgroundAudioManager = wx.getBackgroundAudioManager()
console.log('onPlay')
console.log(backgroundAudioManager.duration, 'backgroundAudioManager.duration')
this.setData({
playStatus: true
})
this.data.parseLyric.seek(backgroundAudioManager.currentTime*1000)
this.toRotate()
},
onPause() {
clearInterval(this.data.timee)
this.data.parseLyric.stop()
console.log('onPause')
this.setData({
playStatus: false
})
},
switch() { // 切换歌曲播放状态
if (this.data.playStatus) { // 切换为暂停状态
const backgroundAudioManager = wx.getBackgroundAudioManager()
backgroundAudioManager.pause()
} else { // 切换为播放状态
const backgroundAudioManager = wx.getBackgroundAudioManager()
backgroundAudioManager.play()
}
},
onTimeUpdate() {
const backgroundAudioManager = wx.getBackgroundAudioManager()
let sliderValue = backgroundAudioManager.currentTime / backgroundAudioManager.duration * 100
this.setData({
currentPosition: this.stotime(backgroundAudioManager.currentTime),
sliderValue: sliderValue,
duration: this.stotime(backgroundAudioManager.duration)
})
// this.data.parseLyric.seek(backgroundAudioManager.currentTime*1000)
},
toRotate() {
this.data.timee && clearInterval(this.data.timee)
this.data.timee = setInterval(() => {
app.globalData.imgRotate = app.globalData.imgRotate + 0.8
this.setData({
imgRotate: app.globalData.imgRotate
})
}, 35)
},
onEnded() {
console.log('onEnded')
this.setData({
playStatus: false
})
if (this.data.mode == 'multiple') {
this.cutNext()
} else {
const backgroundAudioManager = wx.getBackgroundAudioManager()
// 设置了 src 之后会自动播放
backgroundAudioManager.src = this.data.item.src
}
},
slideChange(e) { // 拖动滑块
let value = e.detail.value
this.setData({
sliderValue: value
})
const backgroundAudioManager = wx.getBackgroundAudioManager()
let currentTime = (value / 100) * backgroundAudioManager.duration
backgroundAudioManager.seek(currentTime)
this.data.parseLyric.seek(currentTime*1000)
},
cutPrev() { // 上一首
this.delSongChange('prev')
},
cutNext() { // 下一首
this.delSongChange('next')
},
delSongChange(type) { // 切换歌曲
if (this.data.duration !== 0 && !this.data.isDel) {
if (app.globalData.playList.length > 1) {
clearInterval(this.data.timee)
}
this.data.duration = 0
this.data.parseLyric.stop()
if (type == 'prev') {
if (app.globalData.playIndex > 0) {
app.globalData.playIndex --
} else {
app.globalData.playIndex = app.globalData.playList.length - 1
}
} else {
if (app.globalData.playIndex < app.globalData.playList.length - 1) {
app.globalData.playIndex ++
} else {
app.globalData.playIndex = 0
}
}
let item = app.globalData.playList[app.globalData.playIndex]
wx.setNavigationBarTitle({
title: item.name
})
const backgroundAudioManager = wx.getBackgroundAudioManager()
backgroundAudioManager.title = item.name
backgroundAudioManager.singer = item.author
// 设置了 src 之后会自动播放
backgroundAudioManager.src = item.src
let lyric = Base64.decode(item.lyric)
this.setData({
item: item,
playStatus: !backgroundAudioManager.paused,
parseLyric: new Lyric(lyric, this.handleLyric)
})
this.data.parseLyric.seek(backgroundAudioManager.currentTime*1000)
console.log(this.data.playStatus, 'playStatus')
if (backgroundAudioManager.paused) {
this.data.parseLyric.togglePlay()
}
}
},
// 改变播放模式
changeMode() {
if (this.data.mode == 'multiple') {
this.setData({
mode: 'single'
})
} else {
this.setData({
mode: 'multiple'
})
}
app.globalData.mode = this.data.mode
},
// 时间格式转换
stotime(s) {
let t = ''
if (s > -1) {
let min = Math.floor(s / 60) % 60;
let sec = Math.floor(s) % 60
if (min < 10) { t += '0' }
t += min + ':'
if (sec < 10) { t += '0' }
t += sec
}
return t
},
onUnload() { // 页面卸载
const backgroundAudioManager = wx.getBackgroundAudioManager()
backgroundAudioManager.onTimeUpdate()
backgroundAudioManager.onPlay()
backgroundAudioManager.onPause()
this.data.parseLyric.stop()
clearInterval(this.data.timee)
},
})
微信小程序音乐播放的更多相关文章
- 微信小程序音乐播放器
写在前面 1.入门几天小白的作品,希望为您有帮助,有好的意见或简易烦请赐教 2.微信小程序审核音乐类别已经下架,想要发布选题需慎重.附一个参考链接,感谢https://www.hishop.com.c ...
- 微信小程序音乐播放器组件
wxml <image bindtap="click" src="{{isPlay?'/images/':'/images/'}}"/> JS Pa ...
- 微信小程序---音乐播放和控制
1.效果图如下: 2.代码如下: //index.js //获取应用实例 var app = getApp() Page({ data: { motto: 'Hello World', userInf ...
- 微信小程序音频播放 InnerAudioContext 的用法
今天项目上涉及到了微信小程序播放音频功能,所以今天跟着一些教程做了个简单的播放器 1.实现思路 刚开始想着有没有现成的组件可以直接用,找到了微信的媒体组件 audio,奈何看着 1.6.0版本开始,该 ...
- 微信小程序——音频播放器
先来个效果图韵下味: 需求: 音频的播放,暂停,中间按钮状态的变化,播放时实时更新播放进度: 前进15s,后退15s: 进度条拖动. 一开始想着这3个功能应该挺简单的.不就是播放,暂停,前进,后退么~ ...
- 微信小程序 - 音频播放(1.2版本和1.2版本之后)
不多说了,直接贴code // 1.2版本以后便不在维护 wx.getBackgroundAudioManager({ success:function(res){ var status =res.s ...
- 微信小程序实例源码大全
微信小程序实例源码大全下载 微信小应用示例代码(phodal/weapp-quick)源码链接:https://github.com/phodal/weapp-quick 微信小应用地图定位demo( ...
- 微信小程序源码推荐
wx-gesture-lock 微信小程序的手势密码 WXCustomSwitch 微信小程序自定义 Switch 组件模板 WeixinAppBdNovel 微信小程序demo:百度小说搜索 sh ...
- 近期热门微信小程序demo源码下载汇总
近期微信小程序demo源码下载汇总,乃小程序学习分析必备素材!点击标题即可下载: 即速应用首发!原创!电商商场Demo 优质微信小程序推荐 -秀人美女图 图片下载.滑动翻页 微信小程序 - 新词 GE ...
随机推荐
- 实现一个简单的基于Token的身份认证
这个例子是基于客户端与webapi进行进行交互的身份认证,当然也适用于其他情况下的身份认证. 简单的交互过程: 1.首先输入用户名.密码进行登录操作 2.服务器验证用户名.密码的正确性,验证通过之 ...
- MongoDB3.2.22快速入门与使用【未完待续】
1.CentOS的安装和mongodb,UVE的使用 1.1.CentOS7安装 虚拟机CentOS7安装步骤:https://www.cnblogs.com/wyt007/p/10295834.ht ...
- json格式处理及扩展
<script src="http://apps.bdimg.com/libs/jquery/2.1.4/jquery.js"></script> < ...
- Raptor入门与安装
作为计算机导论的一部分,Raptor的图形化界面可以让编程的初学者更加容易深入理解算法,可以作为一个简单入门的学习工具. 1.Raptor是什么? Raptor( the Rapid Algorith ...
- Django学习之十一:真正理解Django的路由分发和反解url原理
目录 URL Dispatcher 简介 模式概念 对比URLPattern 与 URLResolver (多态的体现) 构建子路由几种方式 反解url算法逻辑 URL Dispatcher 简介 d ...
- js 格林威治时间转正常格式并兼容ios
function timeChange(time) { var date = time.substr(0, 10); //年月日 var hours = time.substring(11, 13); ...
- flex 增长与收缩
flex:auto 将增长值与收缩值设置为1,基本大小为 auto . flex:none. 将增长值与收缩值设置为0,基本大小为 auto .也就是固定大小. 增长: 基本大小 + 额外空间 *( ...
- 自定义编译gdal库
作者:朱金灿 来源:http://blog.csdn.net/clever101 使用下载下来的gdal库的makefile来编译gdal库,生成的gdal库的名字debug版本和release版本都 ...
- 瓦片切图工具gdal2tiles.py改写为纯c++版本
gdal2tiles.py是GDAL库中用于生成TMS瓦片的python代码,支持谷歌墨卡托EPSG:3857与经纬度EPSG:4326两种瓦片,输出png格式图像. gdal2tiles.py Mo ...
- VR一体机如何退出FFBM(QFIL)
前文介绍了通过fastboot命令擦除misc分区,从而退出FFBM的方法.这个方法比较简便,但有不灵的时候,fastboot erase misc命令执行失败,如下图所示. erasing 'mis ...