前言
时隔好几个月终于想起了自己的博客了,哈哈哈,今天给大家分享的是一个我自己的课程实训项目——微信PHP开发《音乐播放器》,顺带给大家也分享一下我自己学习到的知识,话不多说我们开始吧一、简介
- 相信大家都有所了解,学习了这个课程,以后前端的朋友学习Vue框架也会相对来说比较容易,在此之前,我们需要学习一下如何引入库,以及引入库的一些条件,以下链接都是安全可用的官方链接,可以点击跳转,也可以复制,老手可根据目录进行查看,跳过新手教程。
- 因为作者并没有自己的API,本案例所需要的API都来自:
https://blog.csdn.net/weixin_44358443/article/details/114853183 - 还有一些按钮的icon自己去阿里巴巴矢量图标库下载吧,链接:
https://www.iconfont.cn/
二、引入Vant框架
1.引入库
首先你得安装好node.js
如果没有的话,官方链接如下:
https://nodejs.org/en/
在你安装好了node.js的前提下,打开自己的项目根目录
点击路径,输入cmd
会弹出以下界面:
首先需要初始化一下,输入: npm init
输入命令后一路按回车,按到如下所示:
表示初始化成功了,接下来可以引入vant框架了
官网:https://vant-contrib.gitee.io/vant-weapp/#/home
注:照着官网文档做即可这里不做多介绍
2.需要用到的知识
- 网络请求
//因为函数的指向问题,在下面设置数据到data中需要外界的this指向,先定义好变量
var that = this
//利用wx.request这个函数发送请求
wx.request({
//key=这里不做写死,可以实现动态请求不同的参数
url: 'http://iecoxe.top:5000/v1/kuwo/search?key=' + this.data.value,
//使用success函数,附带参数,可以接收返回的值
success: function (res) {
//打印一下,可以查看返回的数值
console.log(res)
//当返回的状态码==400时,说明该请求是坏的,我们弹出提示
if (res.statusCode == 400) {
wx.showToast({
title: '这是一个坏的请求,请重新试试吧',
icon: 'none',
})
}
//将数据设置到data中,这里的that是上面定义的
that.setData({
//获取到名字用来渲染在搜索框
list: res.data.data.list
})
}
})
- 列表渲染
如果不愿意看我的,可以去官方的链接:https://developers.weixin.qq.com/miniprogram/dev/reference/wxml/list.html
在我看来,无非就是利用数组的长度循环,创建出组件,顺便给组件附带该数组的值,例如:
js文件:
Page({
data: {
//定义一个空的数组来接收网络请求回传的数据
list:[],
},
onLoad: function (options) {
//因为函数的指向问题,在下面设置数据到data中需要外界的this指向,先定义好变量
var that = this
//利用wx.request这个函数发送请求
wx.request({
//key=这里不做写死,可以实现动态请求不同的参数
url: 'http://iecoxe.top:5000/v1/kuwo/search?key=周杰伦',
//使用success函数,附带参数,可以接收返回的值
success: function (res) {
//打印一下,可以查看返回的数值
console.log(res)
//当返回的状态码==400时,说明该请求是坏的,我们弹出提示
if (res.statusCode == 400) {
wx.showToast({
title: '这是一个坏的请求,请重新试试吧',
icon: 'none',
})
}
//将数据设置到data中,这里的that是上面定义的
that.setData({
//接收返回的数据中的,data中的data中的list这个数组
list: res.data.data.list
})
}
})
},
})
js中网络请求返回的数据:
wxml文件
<--! 可以看出这返回的是一个多维数组,从状态码中可以看出200是正常的请求,xml的注释太恶心了,下面我就直接写文字了 -->
<view wx:for="{{list}}">
<!-- 数组中的歌名 -->
<view>{{item.album}}</view>
<image src="{{item.albumpic}}"></image>
</view>
结果:
- 页面跳转和页面数据传输
wxml代码:这里以按钮为例子,data-??中可以在点击时附带一些数据回传js中
<button data-id="1" bindtap="testOnClick">
跳转测试
</button>
js代码:
testOnClick:function (e) {
//点击事件附带参数,用e.currentTarget.dataset.??获取到按钮回传的数据,由于我们设置的值是id,这里就写id
wx.navigateTo({
//附带一个id,传递到别的页面,值是点击回传的值
url: '../test/test?id='+e.currentTarget.dataset.id,
})
},
接收页面的js
onLoad: function (options) {
//我是别的页面传递过来的数据,利用options.id获取
var id = options.id;
//设置到data中
this.setData({
id:id
})
},
接收页面的wxml
<!-- 我是传递过来的数据 -->
<view>我是传递过来的数据:{{id}}</view>
三、页面编写,以及js的实现
1.首页
首页:index.wxml
<!-- 通知条 -->
<van-sticky>
<view>
<!-- closeable 模式,在右侧显示关闭按钮 -->
<van-notice-bar mode="closeable" text="技术是开发它的人的共同灵魂。" />
</view>
</van-sticky>
<!-- 搜索栏 -->
<van-sticky>
<view class="container-search" bindtap="search">
<van-search value="" label="" placeholder="阿拉斯加海湾 为你推荐" use-action-slot="true" bind:change="onChange" bind:search="onSearch">
</van-search>
</view>
</van-sticky>
<!-- 三个榜单 官方榜单 特色榜单 场景榜单 -->
<view wx:for="{{ccc}}">
<!-- title -->
<view style="font-size:25px;margin-left:15px;margin-top:5px">
{{item.name}}
</view>
<view class="b">
<!-- 纵向滑动块 -->
<scroll-view class="scroll-view_H" scroll-x="true">
<view class="scroll-view-item_H" wx:for="{{item.list}}" data-name="{{item.name}}" data-id="{{item.sourceid}}" bindtap="OfficialList">
<image src="{{item.pic}}">
</image>
<text>
{{item.name}}
</text>
</view>
</scroll-view>
</view>
</view>
首页:index.wxss
/* 搜索框 */
.container-search{
width: 100%;
}
/* 滑动块 */
.scroll-view_H{
margin-left: 25px;
margin-top: -80px;
white-space: nowrap;
width: 100%
}
.scroll-view-item_H{
display: inline-block;
width: 300rpx;
height: 270rpx;
}
.scroll-view-item_H image{
width: 250rpx;
height: 200rpx;
margin-top: 25px;
}
.scroll-view-item_H text{
margin-left: 25px;
text-align: right;
width: 250rpx;
}
.b{
margin-top: 80px;
margin-left: -15px;
}
首页:index.js
// 获取应用实例
const app = getApp()
Page({
data: {
value: '',
active: 0,
percentage:0,
time: '03:45',
hours: '0' + 0, // 时
minute: '0' + 0, // 分
second: '0' + 0, // 秒
},
testOnClick:function (e) {
wx.navigateTo({
url: '../test/test?id='+e.currentTarget.dataset.id,
})
},
//点击搜索按钮
search: function () {
//点击跳转搜索页面
wx.navigateTo({
url: '../search/search'
})
},
//点击跳转
OfficialList:function (e) {
var that = this
console.log(e.currentTarget.dataset.id)
var name =
wx.navigateTo({
url: '../list/list?id='+e.currentTarget.dataset.id+'&name='+ e.currentTarget.dataset.name,
})
},
aaa:function () {
var that = this
wx.request({
url: 'http://iecoxe.top:5000/v1/kuwo/top?topId=93',
success:function (res) {
console.log(res)
that.setData({
})
}
})
// console.log(this.data.ccc)
},
ccc:function () {
var that = this
wx.request({
url: 'http://iecoxe.top:5000/v1/kuwo/topCategory',
success:function (res) {
console.log(res.data.data)
that.setData({
ccc:res.data.data
})
}
})
console.log(this.data.ccc)
},
//点击事件
onChange(event) {
// event.detail 的值为当前选中项的索引
this.setData({ active: event.detail });
if (event.detail == 1) {
wx.navigateTo({
url: '../play/play',
})
}
},
// 搜索按钮点击事件
onSearch() {
console.log("搜索按钮点击事件")
},
onLoad() {
this.aaa()
this.ccc()
if (wx.getUserProfile) {
this.setData({
canIUseGetUserProfile: true
})
}
},
})
在首页,我获取了api中的热搜榜,利用热搜榜返回的数据来对页面进行渲染,对滑动块进行了规划,也有对应的标题,在囊括滑动块的view中设置对应的点击事件,实现页面的跳转,并附带数据回传,实现数据的跨页面传输,如:歌单的id,等待,在搜索框中,不提供搜索,而是直接进入对应的搜索页进行搜索。
2.搜索页
搜索页:search.wxml
<van-search
value="{{ value }}"
label=""
placeholder="请输入搜索关键词"
use-action-slot="true"
bind:change="onChange"
bind:search="onSearch"
>
<view slot="action" bind:tap="onClick">搜索</view>
</van-search>
<!-- 热门搜索 -->
<view>热门搜索:</view>
<view class="hotsearch" wx:for="{{list}}">
<button class="button-hotsearch" data-name="{{item.key}}" bindtap="hotSearchOnClick">{{item.key}}</button>
</view>
搜索页:search.wxss
/* pages/search/search.wxss */
.hotsearch{
margin-left: 30px;
margin-top: 10px;
}
.button-hotsearch{
margin-bottom: 10px;
font-size: 12px;
float: left;
height: 25px;
margin-right: 10px;
}
搜索页:search.js
// pages/search/search.js
Page({
//热门搜索点击事件
hotSearchOnClick:function (e) {
var name = e.currentTarget.dataset.name
//点击跳转并传递数据(歌名)进行搜索
wx.navigateTo({
url: '../getSearchMusic/getSearchMusic?name='+ name,
})
},
//输入的内容
onChange(e) {
this.setData({
value: e.detail,
});
},
//点击搜索按钮
onClick() {
//打印输入的内容
console.log(this.data.value)
var name = this.data.value
//点击跳转并传递数据(歌名)进行搜索
wx.navigateTo({
url: '../getSearchMusic/getSearchMusic?name='+ name,
})
},
/**
* 页面的初始数据
*/
data: {
value:'阿拉斯加海湾',//设置搜索默认值
list:null,
},
/**
* 生命周期函数--监听页面加载
*/
//获取热门搜索
getHotSearch:function () {
var that = this
wx.request({
url: 'http://iecoxe.top:5000/v1/kuwo/hotSearch',
success: function (res) {
console.log(res)
that.setData({
list:res.data.data
})
}
})
},
onLoad: function (options) {
//在页面加载的时候运行获取热搜的方法
this.getHotSearch()
},
})
获取热门搜索,然后点击时会将对应的值进行传递,在搜索框,输入的值在点击搜索时会传递到获取歌曲列表页面
3.获取搜索歌曲
获取搜索歌曲:getSearchMusic.wxml
<!-- 一直存在的搜索框 -->
<van-search value="{{ value }}" label="" placeholder="请输入搜索关键词" use-action-slot="true" bind:change="onChange"
bind:search="onSearch">
<view slot="action" bind:tap="onClick">搜索</view>
</van-search>
<view style="margin-left:15px;font-weight:bold;">
搜索结果<van-tag style="margin-left:10px;margin-bottom:2px" type="success">单曲</van-tag>
</view>
<view wx:for="{{list}}" style="margin-left:15px">
<van-row>
<van-col span="4" >
<image style="width:120rpx;height:120rpx;margin-top:8px" src="{{item.pic}}"></image>
</van-col>
<van-col span="20">
<view
data-id="{{item.rid}}"
data-albumpic="{{item.albumpic}}"
data-time="{{item.songTimeMinutes}}"
data-artist="{{item.artist}}"
data-name="{{item.name}}"
bindtap="playPageOnClick">
<van-cell-group>
<van-cell title="{{item.name}}" label="{{item.album}}" border="{{ false }}" />
</van-cell-group>
</view>
</van-col>
</van-row>
</view>
获取搜索歌曲:getSearchMusic.js
// pages/getSearchMusic/getSearchMusic.js
Page({
/**
* 页面的初始数据
*/
data: {
value: '',
name: '',
list: null,
rid: '',
allRid: [],//列表歌曲的所有rid
image:[],//图片
singer:[],//歌手
singname:[],//歌名
alltime:[],//时间
},
//输入的内容
onChange(e) {
this.setData({
value: e.detail,
});
},
onClick: function () {
var that = this
wx.request({
url: 'http://iecoxe.top:5000/v1/kuwo/search?key=' + this.data.value,
success: function (res) {
console.log(res)
that.setData({
//获取到名字用来渲染在搜索框
list: res.data.data.list
})
}
})
},
// 进行搜索并获取歌曲url
playPageOnClick: function (e) {
/**
* 传递歌曲id用来获取歌曲url
* 名字
* 图片
* 歌曲结束时间
* 所有的rid
*/
var rid = e.currentTarget.dataset.id
var name = e.currentTarget.dataset.name
var albumpic = e.currentTarget.dataset.albumpic
var songTimeMinutes = e.currentTarget.dataset.time
var artist = e.currentTarget.dataset.artist
var ridList = this.data.allRid
var singnames = this.data.singname
var images = this.data.image
var singers = this.data.singer
var time = this.data.alltime
wx.navigateTo({
url: '../play/play?rid=' + rid + '&name=' + name + '&albumpic=' + albumpic + '&songTimeMinutes=' + songTimeMinutes + '&artist=' + artist+ '&ridList=' + ridList+ '&singnames=' + singnames+ '&images=' + images+ '&singers=' + singers+ '&alltime=' + time,
})
},
/**
* 生命周期函数--监听页面加载
*/
onLoad: function (options) {
var that = this;
// 进行搜索并获取歌曲url
wx.request({
url: 'http://iecoxe.top:5000/v1/kuwo/search?key=' + options.name,
success: function (res) {
console.log(res.data.data.list[0].rid)
console.log(res.data.data.list[0].album)
console.log(res.data.data.list[0].artist)
//利用for循环来写入想要的数据 列表歌曲的所有rid
for (let index = 0; index < res.data.data.list.length; index++) {
var element = res.data.data.list[index].rid;
var album = res.data.data.list[index].album;
var artist = res.data.data.list[index].artist;
var pic120 = res.data.data.list[index].pic120;
var times = res.data.data.list[index].songTimeMinutes;
var rid = 'allRid[' + index + ']';//歌名
var albums = 'singname[' + index + ']';//歌名
var artists = 'singer[' + index + ']';//歌手
var pic = 'image[' + index + ']';//图片
var time = 'alltime[' + index + ']';//图片
that.setData({
[rid]: element,
[albums]: album,
[artists]: artist,
[pic]: pic120,
[time]: times,
});
}
that.setData({
//获取到名字用来渲染在搜索框
value: options.name,
list: res.data.data.list
})
}
})
},
})
将获取到的搜索词进行网络请求,将回传的数据对页面进行渲染,当点击时,会附带数据进行点击回传到js跳转到播放页面,如歌曲的id,歌名,图片的地址等待,还有它们对应的数组,方便对下一曲和上一曲时使用。
4.播放页
播放页:play.wxml
<!--pages/play/play.wxml-->
<van-tabs class='selcetTab' bind:click="onClick_Tab" line-height="0px" title-active-color="red" swipeable="true">
<van-tab title="歌曲" class="van-tabs">
<!-- 歌手+歌名 -->
<view style="width:100%;text-align:center;margin-bottom:10px">{{name}} - {{singer}}</view>
<!-- 图片 -->
<view style="width:100%;text-align:center;margin-bottom:10px">
<image src="{{imageUrl}}" style="width:600rpx;height:600rpx;"></image>
</view>
<!-- 进度条 -->
<view class="progressBar">
<van-progress inactive percentage="{{percentage}}"
pivot-text=" " />
</view>
<!-- 进度条下面的数字 -->
<view class="progressBar">
<van-row>
<van-col span="12">{{minute}}:{{second}}</van-col>
<van-col style="text-align:right" span="12">{{songTimeMinutes}}</van-col>
</van-row>
</view>
<!-- 歌词 -->
<view class="lyric">
</view>
<!-- 播放器 -->
<view class="play">
<van-row>
<!-- 播放模式 -->
<van-col span="4">
<image class="play_0" bindtap="bofangmoshi" src="../image/{{bofangmoshi}}.png"></image>
</van-col>
<!-- 上一曲 -->
<van-col span="4">
<image style="margin-left:20px" bindtap="last" class="play_1" src="../image/last.png"></image>
</van-col>
<!-- 播放 -->
<van-col span="8">
<image class="play_2" bindtap="playClick" src="../image/{{play}}.png"></image>
</van-col>
<!-- 下一曲 -->
<van-col span="4">
<image style="margin-right:20px" bindtap="next" class="play_1" src="../image/next.png"></image>
</van-col>
<!-- 播放列表 -->
<van-col span="4">
<image class="play_3" src="../image/liebiao.png"></image>
</van-col>
</van-row>
</view>
</van-tab>
<van-tab title="歌词">
<view wx:for="{{lyrics}}" style="text-align:center;margin-bottom:10px">
<view>{{item.lyric}}
</view>
</view>
</van-tab>
</van-tabs>
播放页:play.wxss
/* pages/play/play.wxss */
/* 标签页高度设置 */
.selectTab/deep/.van-tabs-line{
height: 100%;
}
.selectTab/deep/.van-tabs-wrap{
height: 100%;
}
/* 进度条 */
/* 进度条下面的数字 */
.progressBar{
margin-top: 10px;
padding-left: 25px;
padding-right: 25px;
}
.play{
text-align: center;
margin-top: 10px;
margin-bottom: 10px;
}
.play_0{
width: 25px;
height: 25px;
margin-top: -5px;
}
.play_1{
width: 25px;
height: 25px;
}
.play_2{
width: 40px;
height: 40px;
margin-top: -10px;
}
.play_3{
width: 30px;
height: 30px;
margin-top: -3px;
}
/* lyric 歌词样式 */
.lyric{
margin: 25px;
}
播放页:play.js
// pages/play/play.js
Page({
/**
* 页面的初始数据
*/
data: {
//歌曲url
Url: "",
//歌名
name: "",
active: 1,
boolean:true,//计时器判断
lyrics: [],//歌词文字
lyricsTime:[],
//进度条数字
number: '',
bofangmoshi: 'liebiaobofang',
play: 'suspend',
percentage: 0, //进度条百分比
songTimeMinutes: '', //歌曲结束时间
minute: '0' + 0, // 分
second: '0' + 0, // 秒
allRidList: [], //所有rid的数组
allSingNames: [], //所有歌名的数组
allImage: [], //所有照片的数组
allSinger: [], //所有歌手名的数组
allTime: [], //所有歌手名的数组
ridNumber: 0, //歌曲的rid位置,如果要下一曲就++
},
/**
*
* 获取到时间,然后进行设置定时器,每1毫秒运行一次,当时间一直时,设置歌词,实现动态渲染
*/
lyricsTime:function () {
console.log(this.data.lyricsTime)
var lyricsTimeInterval = setInterval(function () {
},10)
},
/**
* 进度条
*/
time_percentage: function () {
const that = this
var time = this.data.songTimeMinutes //总时长
var min = time.split(':')[0] //分
var sec = time.split(':')[1] //秒
var t = (Number(min * 60) + Number(sec)) * 10 //获得每百分之一对等的毫秒,用来制作计时器来推动百分比自增
var percentage = this.data.percentage
//进度条百分比设置
var percentageInterval = setInterval(function () {
percentage++
if (percentage > 100) {
//如果进度条=100时,置零
that.setData({
percentage: 0,
play:'play',
boolean:false
})
clearInterval(percentageInterval)
} else {
that.setData({
percentage: percentage
})
}
}, t)
this.setData({
percentageInterval: percentageInterval
})
},
/**
* 保证计时器能够成功的同时,获取到歌曲结束时间,接着时间到了自动暂停计时,然后置零
*/
Time: function () { //计时器
var songTimeMinutes = this.data.songTimeMinutes //总时长
var min = songTimeMinutes.split(':')[0] //分
var sec = songTimeMinutes.split(':')[1] //秒
const that = this
var second = this.data.second
var minute = this.data.minute
var timeIntervar = setInterval(function () { // 设置定时器
second++
//当分钟和秒数一致时
if (minute == min) { //
if (second == sec) {
//置零
second = 0
that.setData({
minute: '0' + 0
})
//停止计时
clearInterval(timeIntervar)
//执行下一首歌
that.next()
}
}
if (second >= 60) {
second = 0 // 大于等于60秒归零
minute++
that.setData({
minute: minute
})
if (minute >= 60) {
minute = 0 // 大于等于60分归零
}
if (minute < 10) {
// 少于10补零
that.setData({
minute: '0' + minute
})
} else {
that.setData({
minute: minute
})
}
}
if (second < 10) {
// 少于10补零
that.setData({
second: '0' + second
})
} else {
that.setData({
second: second
})
}
}, 1000)
this.setData({
timeIntervar: timeIntervar
})
},
/**播放器
* 播放模式
* 上一曲
* 播放暂停
* 下一曲
* 播放列表
*/
//播放模式
bofangmoshi: function () {
if (this.data.bofangmoshi == 'liebiaobofang') {
this.setData({
bofangmoshi: "xunhuanbofang"
})
} else if (this.data.bofangmoshi == 'xunhuanbofang') {
this.setData({
bofangmoshi: "suijibofang"
})
} else if (this.data.bofangmoshi == 'suijibofang') {
this.setData({
bofangmoshi: "danquxunhuan"
})
} else if (this.data.bofangmoshi == 'danquxunhuan') {
this.setData({
bofangmoshi: "liebiaobofang"
})
}
},
//暂停播放
pause:function () {
this.data.innerAudioContext.pause()//暂停音乐
this.setData({//更改图片
play:'play',
boolean:false,
})
//弹出提示
wx.showToast({
title: '暂停',
icon: 'none',
})
//暂停计时器和进度条
clearInterval(this.data.percentageInterval)
clearInterval(this.data.timeIntervar)
},
play:function () {
this.data.innerAudioContext.play()//暂停音乐
this.setData({//更改图片
play:'suspend',
boolean:true,
})
//弹出提示
wx.showToast({
title: '播放',
icon: 'none',
})
//继续进度条和计时器
this.Time()
this.time_percentage()
},
//暂停播放点击
playClick: function () {
var boolean = this.data.boolean
if (boolean) {
this.pause()
} else {
this.play()
}
},
//上一曲
last: function () {
clearInterval(this.data.timeIntervar)
clearInterval(this.data.percentageInterval)
this.setData({
minute: '0' + 0,
second:'0' + 0,
percentage:0
})
wx.showToast({
title: '上一曲',
icon: 'none',
})
//先销毁实例
this.data.innerAudioContext.destroy()
//通过更改url来改变歌曲的播放状态 首先获取到rid,默认为0
var lastRidNumber = this.data.ridNumber
lastRidNumber--
if (lastRidNumber < 0) { //当数字小于0时,那么重置为29
this.setData({
ridNumber: 29
})
}
if (lastRidNumber >= 0) { //当大于等于0时,正常减
this.setData({
ridNumber: lastRidNumber
})
}
var rid = this.data.allRidList[this.data.ridNumber]
var name = this.data.allSingNames[this.data.ridNumber]
var pic = this.data.allImage[this.data.ridNumber]
var singer = this.data.allSinger[this.data.ridNumber]
var time = this.data.allTime[this.data.ridNumber]
if (name == '') {
name = this.data.allSingNames[0]
}
if (this.data.play == 'play') {
this.setData({
play:'suspend',
boolean:true,
})
}
this.setData({
name:name,
singer:singer,
imageUrl:pic,
songTimeMinutes:time,
})
this.lyric(rid)//重新获取歌词
this.getUrl(rid)//重新获取歌曲url
this.Time()
this.time_percentage()
},
//下一曲
next: function () {
clearInterval(this.data.timeIntervar)
clearInterval(this.data.percentageInterval)
this.setData({
minute: '0' + 0,
second:'0' + 0,
percentage:0
})
wx.showToast({
title: '下一曲',
icon: 'none',
})
//先销毁实例
this.data.innerAudioContext.destroy()
//通过更改url来改变歌曲的播放状态 首先获取到rid,默认为0
var nextRidNumber = this.data.ridNumber
nextRidNumber++
/**
* 因为数组有限,所以当大于30时置零
*/
if (nextRidNumber > 29) { //当大于30时 置零
this.setData({
ridNumber: 0
})
}
if (nextRidNumber <= 29) { //当小于等于29时,正常设置
this.setData({
ridNumber: nextRidNumber
})
}
var rid = this.data.allRidList[this.data.ridNumber]
var name = this.data.allSingNames[this.data.ridNumber]
var pic = this.data.allImage[this.data.ridNumber]
var singer = this.data.allSinger[this.data.ridNumber]
var time = this.data.allTime[this.data.ridNumber]
if (name == '') {
name = this.data.allSingNames[0]
}
if (this.data.play == 'play') {
this.setData({
play:'suspend',
boolean:true,
})
}
this.setData({
name:name,
singer:singer,
imageUrl:pic,
songTimeMinutes:time,
})
this.lyric(rid)//重新获取歌词
this.getUrl(rid)//重新获取歌曲url
this.Time()
this.time_percentage()
},
//标签页点击事件
onClick_Tab(event) {
},
//获取歌曲的歌词
lyric: function (rid) {
var that = this
wx.request({
url: 'http://iecoxe.top:5000/v1/kuwo/lyric?rid=' + rid, //这里填写你的接口路径
success: function (res) {
//先获取到歌词
var lyric = res.data.lyric_str
//对歌词进行分割
lyric = lyric.split(']').map(item => item.split('['))
//利用for循环来写入想要的数据
for (let index = 0; index < lyric.length; index++) {
const element = lyric[index][0];
const time = lyric[index][1];
var name = 'lyrics[' + index + '].lyric';
var times = 'lyricsTime[' + index + '].time';
that.setData({
[name]: element,
[times]:time
});
}
}
})
},
//获取歌曲url
getUrl: function (rid) {
var that = this
wx.request({
url: 'http://iecoxe.top:5000/v1/kuwo/song?rid=' + rid, //这里填写你的接口路径
success: function (res) {
console.log(res.data.url)
console.log(res.statusCode)
if (res.statusCode == 400) {
wx.showToast({
title: '该歌曲不存在或无法播放,请下一首',
icon: 'none',
})
}
console.log(res)
that.myAudio(res.data.url)
}
})
},
//设置音乐播放器组件
myAudio: function (url) {
this.lyricsTime()
const innerAudioContext = wx.createInnerAudioContext()
//设置到data里面
this.setData({
innerAudioContext:innerAudioContext
})
//默认自动播放
innerAudioContext.autoplay = true
innerAudioContext.src = url
innerAudioContext.onPlay(() => {
wx.showToast({
title: '开始播放',
icon: 'none',
})
})
innerAudioContext.onError((res) => {
console.log(res.errMsg)
console.log(res.errCode)
})
},
/**
* 生命周期函数--监听页面加载
*/
onLoad: function (options) {
var n = options.ridList.split(',')
var name = options.singnames.split(',')
var image = options.images.split(',')
var singer = options.singers.split(',')
var time = options.alltime.split(',')
this.setData({
"rid": options.rid,
name: options.name,
imageUrl: options.albumpic,
singer: options.artist,
songTimeMinutes: options.songTimeMinutes,
allRidList: n,
allSingNames: name,
allImage: image,
allSinger: singer,
allTime:time,
})
console.log(this.data.allTime)
this.getUrl(options.rid) //歌曲rul
this.lyric(options.rid) //歌词
this.Time()//计时器
this.time_percentage()//进度条
},
/**
* 生命周期函数--监听页面卸载
*/
onUnload: function () {
this.data.innerAudioContext.destroy()
}
})
在播放页使用了wx.createInnerAudioContext()组件,因为官方的audio组件有很多bug,所以不对此进行使用,这个组件相对来说比较方便,也可以在后台播放,我在这里限制了不能让它离开了播放页还在播放,不然会有多重歌曲播放的bug,点击事件播放暂停没啥好说的,主要是计时器setInterval()的使用,在计时器这方面我对进度条包含在里面,当暂停时,进度条也会暂停,启动时也会启动,下一曲会清空进度条。
5.榜单列表页
榜单列表页:list.wxml
<!--pages/list/list.wxml-->
<view style="background-color:#FFFAF0">
<view>
<van-row>
<van-col span="10">
<image style="width:350rpx;height:300rpx" src="{{list.img}}"></image>
</van-col>
<van-col span="14">
<view style="padding-top:15px;text-align: center;font-size:22px">{{name}}</view>
<view style="padding-top:25px;padding-left:38px;">更新时间:
</view>
<view style="padding-top:5px;padding-left:38px;">{{list.pub}}</view>
</van-col>
</van-row>
</view>
<view style="margin-top:10px;margin-left:15px" wx:for="{{list.musicList}}"
bindtap="onClick"
data-id="{{item.albumid}}"
data-name="{{item.album}}"
data-artist="{{item.artist}}"
data-time="{{item.songTimeMinutes}}"
data-albumpic="{{item.albumpic}}">
<van-row>
<van-col span="6">
<image style="width:150rpx;height:150rpx" src="{{item.albumpic}}"></image>
</van-col>
<van-col span="18">
<!-- 歌名 -->
<view>{{item.album}}</view>
<view style="padding-top:15px;">{{item.artist}}</view>
</van-col>
</van-row>
</view>
</view>
榜单列表页:list.js
// pages/list/list.js
Page({
/**
* 页面的初始数据
*/
data: {
list:'',
allRid: [],//列表歌曲的所有rid
image:[],//图片
singer:[],//歌手
singname:[],//歌名
alltime:[],//时间
},
onClick:function (e) {
var rid = e.currentTarget.dataset.id
var name = e.currentTarget.dataset.name
var albumpic = e.currentTarget.dataset.albumpic
var songTimeMinutes = e.currentTarget.dataset.time
var artist = e.currentTarget.dataset.artist
var ridList = this.data.allRid
var singnames = this.data.singname
var images = this.data.image
var singers = this.data.singer
var time = this.data.alltime
wx.navigateTo({
url: '../play/play?rid=' + rid + '&name=' + name + '&albumpic=' + albumpic + '&songTimeMinutes=' + songTimeMinutes + '&artist=' + artist+ '&ridList=' + ridList+ '&singnames=' + singnames+ '&images=' + images+ '&singers=' + singers+ '&alltime=' + time,
})
},
/**
* 生命周期函数--监听页面加载
*/
onLoad: function (options) {
var that = this
console.log(options.id)
console.log(options.name)
wx.request({
url: 'http://iecoxe.top:5000/v1/kuwo/top?topId='+options.id,
success:function (res) {
console.log(res.data.data)
//利用for循环来写入想要的数据 列表歌曲的所有rid
for (let index = 0; index < res.data.data.musicList.length; index++) {
var element = res.data.data.musicList[index].albumid;
var album = res.data.data.musicList[index].album;
var artist = res.data.data.musicList[index].artist;
var pic120 = res.data.data.musicList[index].pic120;
var times = res.data.data.musicList[index].songTimeMinutes;
var rid = 'allRid[' + index + ']';//id
var albums = 'singname[' + index + ']';//歌名
var artists = 'singer[' + index + ']';//歌手
var pic = 'image[' + index + ']';//图片
var time = 'alltime[' + index + ']';//图片
that.setData({
[rid]: element,
[albums]: album,
[artists]: artist,
[pic]: pic120,
[time]: times,
});
}
that.setData({
name:options.name,
list:res.data.data
})
}
})
},
})
将传递过来的歌单id进行发送请求,用返回的数据将页面渲染,点击时传递对应的歌曲id,歌名等数据进行跳转到播放页,并且将数组传递,唯一不足的地方,就是上下一曲时,最多只能30首歌。
6.对应页面的json文件
因为使用了框架就需要在json文件中引入对应的库,所以我在编写的过程中并没有写在app.json中,在这里建议大家直接丢到app.json中,如果有重复的删了就是了
//index.json
{
"usingComponents": {
"van-search": "@vant/weapp/search/index",
"van-notice-bar": "@vant/weapp/notice-bar/index",
"van-tab": "@vant/weapp/tab/index",
"van-tabs": "@vant/weapp/tabs/index",
"van-count-down": "@vant/weapp/count-down/index"
}
}
//search.json
{
"usingComponents": {
"van-search": "@vant/weapp/search/index"
}
}
//getSearchMusic.json
{
"usingComponents": {
"van-search": "@vant/weapp/search/index",
"van-cell": "@vant/weapp/cell/index",
"van-cell-group": "@vant/weapp/cell-group/index",
"van-row": "@vant/weapp/row/index",
"van-col": "@vant/weapp/col/index",
"van-button": "@vant/weapp/button/index",
"van-tag": "@vant/weapp/tag/index"
}
}
//play.json
{
"usingComponents": {
"van-tab": "@vant/weapp/tab/index",
"van-tabs": "@vant/weapp/tabs/index",
"van-progress": "@vant/weapp/progress/index",
"van-row": "@vant/weapp/row/index",
"van-col": "@vant/weapp/col/index",
"van-slider": "@vant/weapp/slider/index",
"van-sticky": "@vant/weapp/sticky/index"
}
}
//list.json
{
"usingComponents": {
"van-card": "@vant/weapp/card/index"
}
}
总结
以上就是我要给大家带来的内容,本文仅仅简单介绍了这个小项目的一部分,还有很多很多的功能没有进行优化,也有很多遗憾没有实现,本文所有代码都是自己手敲的,命名规则比较混乱。你有更好的建议,欢迎进行评论。你有什么困惑,也可以添加我的个人QQ:643895437,欢迎和大家探讨问题。再次声明,该api是另外一个博主的,up本身并没有api。
感谢你能看到这里,如果觉得这篇文章对你有所帮助,请给我点个赞吧,谢谢啦。