今天想要分享的一个项目是作者自己在暑假实训期间制作的一款仿网易音乐的音乐播放小程序,将会为大家展示小程序的具体功能以及实现代码,比较适合前端初学者拿来参考。(本人也是技艺不精,若有说的不对的地方,望指摘,勿喷,友好交流)
一、项目介绍
本音乐播放小程序有歌曲列表,个人信息,搜索三个模块
二、小程序的效果图
歌曲列表界面:
这部分相当于一个简易的首页部分,包含轮播图,歌曲列表,搜索框按钮,点击搜索框按钮就会发生跳转,然后跳转到搜素界面
搜索界面:
这部分是搜索界面,在搜索框内输入想要搜索的歌曲或者歌手就会跳转到歌曲列表界面,然后在轮播图的下面展示出搜索的结果
歌曲播放界面:
点击歌曲列表后面的播放按钮就可以跳转到歌曲的播放界面并进行播放,歌曲播放界面有暂停,上一首,下一首,随机播放,单曲循环等功能
歌词滚动界面:
歌曲播放界面向左滑动便可以到达歌词部分,根据歌曲进度使对应的歌词部分显红
个人信息界面:
该部分是个人信息界面
三、部分代码实现
歌曲列表部分的:
// index.js
[ ] // 获取应用实例
const app = getApp()
Page({
data: {
// 轮播图数组
'swiperList':[{
'goods_id':'1',
'image_src':'/images/lunbo/lunbo1.jpg',
'open_type':'navigate'
},
{
'goods_id':'2',
'image_src':'/images/lunbo/lunbo2.jpg',
'open_type':'navigate'
},
{'goods_id':'3',
'image_src':'/images/lunbo/lunbo3.jpg',
'open_type':'navigate'
}
] ,
//歌曲数组
songs:[],
// 定义歌曲的数组
},
onLoad: function (options) {
},
onShow(){
const app=getApp()
let songs=app.globalData.data
console.log(songs);
this.setData({
songs,
})
},
// 点击事件函数
gotoplay:function(e){
var id = e.currentTarget.dataset.id;
// 定义一个空数组
var ids = [];
// 遍历歌曲列表
for(var i=0;i<this.data.songs.length;i++){
ids.push(this.data.songs[i].id);
}
console.log("点击事件进入的方法");
wx.navigateTo({
url:'/pages/paly/play?mid='+ id + "&ids=" + ids,
})
}
})
歌曲播放部分:
// pages/paly/play.js
Page({
/**
* 页面的初始数据
*/
data: {
state:"play",
id:"",
ids:[],
song:null,
lyricArray:[],
// 竖向滚动条初始值为0
marginTop:0,
currentIndex:0,
// 播放模式
mode:'loop',
// 播放时间
currentTime:"00:00",
// 总时间
timeLength:"03:30",
max:0,
move:0,
likeState:"unlike"
},
/**
* 生命周期函数--监听页面加载
*/
// 控制歌曲的播放状态
playOrPause:function(){
var musicState=this.data.state;
if(musicState=='play'){
this.setData({
state:'pause'
})
this.audioCtx.pause()
}else{
this.setData({
state:'play'
})
this.audioCtx.play()
}
},
// 上一首歌曲的函数
prevSong:function(){
var currentId = this.data.id;
// 定义一个变量记录当前歌曲的下标
var index = 0;
// 根据id值找出当前歌曲的下标
for(var i =0;i<this.data.ids.length;i++){
// 判断一下当前歌曲是否一致
if(currentId == this.data.ids[i]){
index = i;
break;
}
}
var prevIndex =index ==0?this.data.ids.length-1 : index-1;
var prevId = this.data.ids[prevIndex];
// 修改当前歌曲的id
this.setData({
id:prevId
})
// 调用获取歌曲详情的函数
this.getSongInfoById();
// 播放新的歌曲
this.audioCtx.play();
},
// 下一首歌曲的函数
nextSong:function(){
var currentId = this.data.id;
// 定义一个变量记录当前歌曲的下标
var index = 0;
// 根据id值找出当前歌曲的下标
for(var i =0;i<this.data.ids.length;i++){
// 判断一下当前歌曲是否一致
if(currentId == this.data.ids[i]){
index = i;
break;
}
}
var nextIndex =index ==this.data.ids.length-1 ? 0: index+1;
var nextId = this.data.ids[nextIndex];
// 修改当前歌曲的id
this.setData({
id:nextId
})
// 调用获取歌曲详情的函数
this.getSongInfoById();
// 播放新的歌曲
this.audioCtx.play();
},
// 切换播放模式的方法
changeMode:function(params){
var currentMode =this.data.mode;
if(currentMode=='loop'){
this.setData({
mode:'single'
})
}else{
this.setData({
mode:'loop'
})
}
},
// 当歌曲播放完后的函数
changeMusic:function () {
// 判断当前的模式
var mode = this.data.mode;
var currentId = this.data.id;
// 单曲循环
if(mode == 'single'){
// 单曲循环设置自己原本的id
this.setData({
id:currentId
})
// 刷新播放状态
this.getSongInfoById();
this.audioCtx.play();
}else{
this.nextSong();
}
},
// 收藏歌曲的方法
songLove:function(params){
var currentState =this.data.likeState;
if(currentState=='unlike'){
this.setData({
likeState:'like'
})
}else{
this.setData({
likeState:'unlike'
})
}
},
// 根据歌曲id来获取歌词的方法
getLyricById:function(){
var that = this;
var currentId = this.data.id;
wx.request({
url: 'http://music.163.com/api/song/lyric?os=pc&id='+ currentId +'&lv=-1&kv=-1&tv=-1',
success:function(result){
// 解析歌词在字符串里
var lyrics = result.data.lrc.lyric;
// 调用解析歌词的方法
var result = that.parseLyric(lyrics);
// 调用去掉空歌词的方法
var finalResult = that.sliceNull(result);
that.setData({
lyricArray:finalResult
})
}
})
},
// 解析歌词的方法(正则表达式)
parseLyric:function(lyrics){
// 存储时间和歌词且一一对应
var lyricResult =[];
// 将歌词组成的字符串组成每句歌词组成的数组
var lyricArray = lyrics.split("\n");
// 判断最后一个元素是否为空。如果为空则删除
if(lyricArray[lyricArray.length-1] == ""){
lyricArray.pop();
}
var pattern = /\[\d{2}:\d{2}\.\d{2,3}\]/;
// 遍历数组中的每一句歌词
lyricArray.forEach(function(v,i,a){
var real_lyric = v.replace(pattern,"");
// 对每一句歌词处理,将时间单独提取出来
var time = v.match(pattern);
// 时间里的中括号不要
// js中的最后一个元素的下标是长度-1或者-1
if(time !=null){
var timeResult = time[0].slice(1,-1);
// 对结果进行一个切分
var timeArray = timeResult.split(":");
var finalTime = parseFloat(timeArray[0])*60 +parseFloat(timeArray[1]);
lyricResult.push([finalTime,real_lyric]);
}
})
// 返回歌词时间数组
return lyricResult;
},
// 去掉空歌词,保留非空歌词的方法
sliceNull:function(lyricArray){
var result = [];
for(var i=0;i<lyricArray.length;i++){
if(lyricArray[i][1]!=""){
result.push(lyricArray[i]);
}
}
return result;
},
// 歌词与时间匹配的方法
//播放进度触发
changeTime:function(e){
var currentTime = e.detail.currentTime;
var lyricArray = this.data.lyricArray;
if(this.data.currentIndex>=8){
this.setData({
marginTop:(this.data.currentIndex-8)*30
})
}
if(this.data.currentIndex == lyricArray.length-2){
if(currentTime>=lyricArray[lyricArray.length-1][0]){
this.setData({
currentIndex:lyricArray.length-1
})
}
}else{
for(var i=0;i<lyricArray.length-1;i++){
if(currentTime>=lyricArray[i][0] && currentTime<lyricArray[i+1][0]){
this.setData({
currentIndex:i
})
}
}
}
//进度条更新
var timeLength = e.detail.duration;
var sum_m = Math.floor(timeLength/60);
var sum_s = Math.floor(timeLength%60);
// 个位数补齐0
if(sum_m<10){
sum_m="0"+sum_m
}
if(sum_s<10){
sum_s="0"+sum_s
}
// 定义播放时间
var play_m = Math.floor(currentTime/60);
var play_s = Math.floor(currentTime%60);
// 个位数补齐0
if(play_m<10){
play_m="0"+play_m
}
if(play_s<10){
play_s="0"+play_s
}
// 进度条更新
this.setData({
currentTime:play_m+":"+play_s,
timeLength:sum_m+":"+sum_s,
max:timeLength,
move:currentTime
})
},
// 进度条拖拽的方法
sliderChange:function(e){
var that = this;
var currentValue = e.detail.value;
this.setData({
move:currentValue
})
// 跳转到指定播放的秒数位置
that.audioCtx.seek(currentValue);
// 修改当前播放时间
// this.setData({
// action:{
// method:'setCurrentTime',
// data:currentValue
// }
// })
},
// 根据歌曲的id找歌曲的详情
getSongInfoById:function(){
var currentId = this.data.id;
var that = this;
wx.request({
url: 'https://music.163.com/api/song/detail/?id='+ currentId + '&ids=['+ currentId +']',
success:function(result){
var musicInfo = result.data.songs[0];
console.log(musicInfo);
that.setData({
song:musicInfo
})
}
})
},
onLoad:function (options) {
var mid = options.mid;
var idStr = options.ids;
var ids = idStr.split(",");
this.setData({
id:mid,
ids:ids
})
this.getSongInfoById();
this.getLyricById();
},
/**
* 生命周期函数--监听页面初次渲染完成
*/
onReady:function() {
this.audioCtx = wx.createAudioContext('myAudio');
this.audioCtx.play();
},
/**
* 生命周期函数--监听页面显示
*/
onShow() {
},
/**
* 生命周期函数--监听页面隐藏
*/
onHide() {
},
/**
* 生命周期函数--监听页面卸载
*/
onUnload() {
},
/**
* 页面相关事件处理函数--监听用户下拉动作
*/
onPullDownRefresh() {
},
/**
* 页面上拉触底事件的处理函数
*/
onReachBottom() {
},
/**
* 用户点击右上角分享
*/
onShareAppMessage() {
}
})
<!--pages/paly/play.wxml-->
<view class="content">
<image class="big_img"
src="{{song.album.picUrl}}"></image>
<view class="title">{{song.name}}</view>
<!-- 中间封面和歌词 -->
<view class="middle">
<swiper class="middle-swiper">
<!-- 封面区域 -->
<swiper-item class="cd-wrapper">
<view class="cd-image">
<image style="animation-play-state:{{state == 'play'? 'running': 'paused'}}" src="{{song.album.picUrl}}"></image>
</view>
</swiper-item>
<!-- 歌词区域 -->
<swiper-item>
<!-- scroll-view可以滚动 -->
<scroll-view class="lyric-wrapper" scroll-y="true" scroll-top="{{marginTop}}">
<!-- 存放所有歌词 -->
<view class="contentArray">
<block wx:for="{{lyricArray}}" wx:for-index="index" wx:for-item="lyric">
<text class="{{currentIndex == index?'currentLyric':''}}">{{lyric[1]}}</text>
</block>
</view>
</scroll-view>
</swiper-item>
</swiper>
</view>
<!-- 播放控制按钮 -->
<!-- 进度条 -->
<view class="timeBox">
<view class="play_time">{{currentTime}}</view>
<!-- max代表总的长度,value是当前进度 -->
<slider bindchange="sliderChange" activeColor="red" block-size="14" max="{{max}}" value="{{move}}"></slider>
<view class="end_time">{{timeLength}}</view>
</view>
<!-- 播放相关的按钮 -->
<view class="controls">
<!-- 切换上一首歌曲 -->
<image bindtap="changeMode" src="/images/tabar/{{mode =='loop'? 'loop' : 'single'}}.png"></image>
<image bindtap="prevSong" src="/images/tabar/prev.png"></image>
<image bindtap="playOrPause" src="/images/tabar/{{state =='play'? 'pause' : 'play'}}.png"></image>
<image bindtap="nextSong" src="/images/tabar/next.png"></image>
<image bindtap="songLove" src="/images/tabar/{{likeState =='unlike'? 'unlike1':'like'}}.png"></image>
</view>
</view>
<!-- 当播放进度改变时触发changtime函数 -->
<audio bindended="changeMusic" bindtimeupdate="changeTime" src="http://music.163.com/song/media/outer/url?id={{id}}.mp3" id="myAudio">
</audio>
最后,说一下本人的学习心得,前端相关学习视频推荐,b站黑马程序员pink老师系列,本人认为作为前端的初学者来说,pink老师的课风趣幽默,技术知识点讲的非常细致,其他的同学们可以去参考看看。