一:学习目标:
- 掌握swiper组件、scroll-view组件的使用;
- 掌握image组件的使用;
- 掌握slider组件的使用;
- 掌握音频API的使用;
二:目录:
1. 开发前的准备
1.1 音乐小程序项目展示:
1.1.1:音乐推荐界面展示:
1.1.2:播放器界面展示:
1.1.3:播放列表界面展示:
1.2:项目分析:
①:音乐播放器项目(项目结构图)
- tab导航栏
- content内容区
- player音乐播放控件
②:音乐播放器小程序项目主要文件:
- app.js:应用程序的逻辑文件
- app.json:应用程序的配置文件
- pages/index/index1.js:index页面的逻辑文件
- pages/index/index1.json:index页面的配置文件
- pages/index/index1.wxss:index页面的样式文件
- pages/index/index1.wxml:index页面的结构文件
- pages/index/info.wxml:“音乐推荐”标签页的结构文件
- pages/index/play.wxml:“播放器”标签页的结构文件
- pages/index/playlist.wxml:“播放列表”标签页的结构文件
- images:图片文件
1.3:项目初始化:
开发者工具创建项目:
2. 标签页切换
2.1:任务分析:
标签页和页面结构图:
2.2 前导知识:
swiper组件常用属性:
可选值 |
说明 |
默认 |
indicator-dots |
Boolean |
是否显示面板指示点,默认为false |
indicator-color |
Color |
指示点颜色,默认为rgba(0,0,0,.3) |
indicator-active-color |
Color |
当前选中的指示点颜色,默认为#000000 |
autoplay |
Boolean |
是否自动切换,默认为false |
current |
Number |
当前所在滑块的index,默认为0 |
current-item-id |
String |
当前所在滑块的item-id(不能同时指定current) |
interval |
Number |
自动切换时间间隔(毫秒),默认为5000 |
duration |
Number |
滑动动画时长(毫秒),默认为500 |
circular |
Boolean |
是否采用衔接滑动,默认为false |
vertical |
Boolean |
滑动方向是否为纵向,默认为false |
bindchange |
EventHandle |
current改变时会触发change事件 |
swiper组件编写滑动页面结构 index1.wxml(本项目已完成,无此项代码)
③:include主要用途:
- 将代码拆分到多个文件中,可以更方便地查找代码。
- 将代码公共部分抽取出来。通过外部文件引入。
④:编写页面结构和样式-tab导航栏
2.3 编写页面结构和样式 :
①:音乐小程序基础页面和样式:
②:音乐小程序基础页面和样式-tab导航的样式:
tab导航样式效果:
2.4:实现标签页切换:
单击导航栏选项卡实现标签页切换(js):
通过滚动事件切换页面效果(js):
效果:
3. 音乐推荐
3.1 任务分析
音乐推荐页面结构图:
3.2 前导知识
image组件属性及说明:
可选值 |
说明 |
默认 |
src |
String |
图片资源地址 |
mode |
String |
图片裁剪、缩放的模式,默认为'scaleToFill' |
lazy-load |
Boolean |
图片是否懒加载,默认为false。只针对page与scroll-view下的image有效 |
binderror |
HandleEvent |
图片发生错误时的事件 |
bindload |
HandleEvent |
图片载入完成时的事件 |
scaleToFill |
不保持纵横比缩放图片,使图片的宽高完全拉伸至填满image元素。适用于容器与图片宽高比相同的情况,如果不同,图片会变形。 |
aspectFit |
保持纵横比缩放图片,使图片的长边能完全显示出来。适用于将图片完整显示出来。例如,详情页的图片 |
aspectFill |
保持纵横比缩放图片,只保证图片的短边能完全显示出来,长边将会发生截取。适用于容器固定,图片自动缩放的情况,如列表页的缩略图 |
widthFix |
宽度不变,高度自动变化,保持原图宽高比不变 |
top |
不缩放图片,只显示图片的顶部区域 |
bottom |
不缩放图片,只显示图片的底部区域 |
center |
不缩放图片,只显示图片的中间区域 |
left |
不缩放图片,只显示图片的左边区域 |
right |
不缩放图片,只显示图片的右边区域 |
top left |
不缩放图片,只显示图片的左上边区域 |
top right |
不缩放图片,只显示图片的右上边区域 |
bottom left |
不缩放图片,只显示图片的左下边区域 |
bottom right |
不缩放图片,只显示图片的右下边区域 |
image组件缩放模式和裁剪模式测试(效果图):
3.3 轮播图
在info.wxml中使用swiper组件实现轮播图:
3.4 功能按钮
flex布局实现功能按钮:
flex布局样式:
效果图:
3.5 热门音乐
①:flex布局实现页面布局:
flex布局实现页面布局(样式):
②:index页面底部播放:
index页面底部播放(样式):
index页面播放底部呈现效果 :
4. 播放器
4.1 任务分析
4.1.1 播放器的具体功能进行分析:
- 音乐信息:显示当前播放曲目的标题和艺术家。
- 专辑封面:当音乐播放时,专辑封面会顺时针旋转。
- 播放进度:显示播放进度,调节音乐进度。
4.1.2 播放器标签页结构图:
4.2 前导知识
①:音频API接口的属性及说明:
可选值 |
名称 |
说明 |
属性 |
src |
音频资源的地址,用于直接播放 |
startTime |
开始播放的位置(秒),默认为0 |
|
autoplay |
是否自动开始播放,默认为false |
|
loop |
是否循环播放,默认为false |
|
volume |
音量。范围0~1。默认为1 |
属性 |
duration |
音频的长度(秒)。在当前有合法的src时返回(只读) |
currentTime |
音频的播放位置(秒)。在当前有合法的src时返回(只读) |
|
paused |
当前是是否暂停或停止状态(只读) |
方法 |
play() |
播放 |
pause() |
暂停(暂停后的音频再播放会从暂停处开始播放) |
|
stop() |
停止(停止后的音频再播放会从头开始播放) |
|
seek() |
跳转到指定位置 |
|
destroy() |
销毁当前实例 |
|
onCanplay() |
音频进入可以播放状态的事件(参数为回调函数) |
|
onPlay() |
音频播放事件(参数为回调函数) |
方法 |
onPause() |
音频暂停事件(参数为回调函数) |
onStop() |
音频停止事件(参数为回调函数) |
|
onEnded() |
音频自然播放至结束的事件(参数为回调函数) |
|
onSeeked() |
音频进行跳转操作的事件(参数为回调函数) |
|
onTimeUpdate() |
音频播放进度更新事件(参数为回调函数) |
|
onError() |
音频播放错误事件(参数为回调函数) |
②:innerAudioContext案例使用:
③:slider组件属性及说明:
可选值 |
类型 |
说明 |
min |
Number |
最小值,默认为0 |
max |
Number |
最大值,默认为100 |
step |
Number |
步长,取值大于0,可被(max-min)整除,默认为1 |
value |
Number |
当前取值,默认为0 |
activeColor |
Color |
已选择的颜色,默认为#1aad19 |
backgroundColor |
Color |
背景条的颜色,默认为#e9e9e9 |
block-size |
Number |
滑块的大小,取值范围为12~28,默认为28 |
block-color |
Color |
滑块的颜色,默认为#ffffff |
show-value |
Boolean |
是否显示当前value,默认为false |
bindchange |
EventHandle |
完成一次拖动后触发的事件 |
bindchanging |
EventHandle |
拖动过程中触发的事件 |
4.3 定义基础数据
4.4 实现音乐播放功能
①:音乐播放逻辑代码(js):
②:底部播放器暂停/播放按钮控制歌曲:
js:
③:播放器切换到下一首歌曲:
js:
4.5 编写播放器页面
①:播放页面 play.wxml 结构代码:
播放页面样式代码:
效果:
②:播放器样式代码:
③:通过样式动画实现海报的旋转功能:
海报的旋转功能样式代码:
4.6 控制播放进度
播放器页面下方的滑块结构(play.wxml中):
滑块样式代码:
5. 播放列表
5.1 任务分析结构图
5.2 编写页面结构和样式
控制进度条的长度控制歌曲播放进度:
控制进度条的长度控制歌曲播放进度样式:
5.3 实现换曲功能
换曲功能(js)代码:
代码:
pages/index/index1.js:
// pages/index/index1.js
Page({
/**
* 页面的初始数据
* item控制页面显示的,0-2,表示显示不同的页面和顶部不同的导航
* state控制图标或当前音乐播放的状态:'paused'表示暂停,'running'表示在运行
*/
data: {
item:2,
state:'paused',
playindex:0,
playlist:[{
id:1,
title:"운명(命运)",
singer:"why",
coverImage:"../images/cover.jpg",
src:"http://www.ytmp3.cn/down/78392.mp3"
},{
id:2,
title:"玫瑰花的葬礼",
singer:"许嵩",
coverImage:"../images/cover.jpg",
src:"http://www.ytmp3.cn/down/78393.mp3"
},{
id:3,
title:"小酒窝",
singer:"蔡卓妍/林俊杰",
coverImage:"../images/cover.jpg",
src:"http://www.ytmp3.cn/down/78378.mp3"
},{
id:4,
title:"十年",
singer:"陈奕迅",
coverImage:"../images/cover.jpg",
src:"http://www.ytmp3.cn/down/78384.mp3"
}],
currentplay:{
id:0,
title:"",
singer:"",
coverImage:"",
src:"",
duration:"00:01",
currentTime:"00:01",
}
},
changeItem:function(e){
this.setData({
item:e.target.dataset.item
})
},
changeTab:function(e){
console.log(e)
this.setData({
item:e.detail.current
})
},
play:function(e){
// 还缺音乐播放里面暂停播放的逻辑
this.audioCtx.play();
this.setData({
state:'running'
})
},
pause:function(e){
// 还缺音乐播放里面暂停播放的逻辑
this.audioCtx.pause();
this.setData({
state:'paused'
})
},
next:function(e){
var index = this.data.playindex
var count = this.data.playlist.length;
index = index +1;
index = index%count;
this.setMusic(index)
this.play()
},
changeMusic:function(e){
console.log(e)
var index = e.currentTarget.dataset.index;
this.setMusic(index);
this.play();
},
scroll: function(e) {
console.log(e.detail)
},
testBind:function(e){
console.log(e)
} ,
testBinding:function(e){
console.log(e)
} ,
/**
* 生命周期函数--监听页面加载
*/
onLoad(options) {
},
/**
* 生命周期函数--监听页面初次渲染完成
*/
audioCtx:null,
onReady() {
this.audioCtx = wx.createInnerAudioContext();
this.setMusic(0);//默认选择第一首
var outthis = this;
this.audioCtx.onTimeUpdate(function(){
var duration = outthis.timeFormat(outthis.audioCtx.duration);
var currentTime = outthis.timeFormat(outthis.audioCtx.currentTime);
console.log("播放回调方法调用"+duration+";currenttime"+currentTime)
outthis.setData({
'currentplay.currentTime':currentTime,
'current.duration':duration
})
});
},
timeFormat:function(time){
var minutes = Math.floor(time/60);
var lminutes = ""
if(minutes<10){
lminutes = '0'+ minutes
}else{
lminutes = minutes
}
var seconds = Math.floor(time)%60;
var lseconds = ""
if(seconds<10){
lseconds = '0'+ seconds
}else{
lseconds = seconds;
}
console.log(lminutes+":"+lseconds)
return(lminutes+":"+lseconds);
},
setMusic:function(tempIndex){
//当前播放歌曲的信息
var currentMusic = this.data.playlist[tempIndex];
//设置音频播放的地址
this.audioCtx.src = currentMusic.src;
this.setData({
playindex:tempIndex,
'currentplay.id':currentMusic.id,
'currentplay.title':currentMusic.title,
'currentplay.singer':currentMusic.singer,
'currentplay.coverImage':currentMusic.coverImage,
'currentplay.src':currentMusic.src,
});
},
/**
* 生命周期函数--监听页面显示
*/
onShow() {
},
/**
* 生命周期函数--监听页面隐藏
*/
onHide() {
},
/**
* 生命周期函数--监听页面卸载
*/
onUnload() {
},
/**
* 页面相关事件处理函数--监听用户下拉动作
*/
onPullDownRefresh() {
},
/**
* 页面上拉触底事件的处理函数
*/
onReachBottom() {
},
/**
* 用户点击右上角分享
*/
onShareAppMessage() {
}
})
pages/index/index1.wxss:
.tab{
display: flex;
flex-direction: row;
}
.tab-item{
flex: 1;
text-align: center;
border-bottom: 6rpx solid #eee;
font-size: 10pt;
line-height: 72rpx;
color: white;
}
.tab-item.active{
border-bottom: 6rpx solid #c25b5b;
color: #c25b5b;
}
page{
background-color: #1a1818;
display: flex;
flex-direction: column;
height: 100%;
color: #ccc;
}
.content{
flex: 1;
}
.content-info-portal{
display: flex;
flex-direction: row;
}
.content-info-portal image{
width: 120rpx;
height:120rpx;
}
/* 轮播图 */
.content-info-side{
height: 150px;
}
.content-info-side image{
width: 100%;
height: 100%;
}
.content >swiper{
height: 100%;
}
/* 功能按钮 */
.content-info-portal{
display: flex;
flex-direction: row;
}
.content-info-portal >view{
flex: 1;
font-size: 11pt;
text-align: center;
}
.content-info-portal image{
width: 120rpx;
height: 120rpx;
display: block;
margin: 20rpx auto;
}
.list-inner{
display: flex;
flex-wrap: wrap;
flex-direction: row;
}
.list-item{
flex:1;
margin: 15rpx;
font-size: 10pt;
}
.list-item image{
width: 200rpx;
height: 200rpx;
display: block;
margin: 0 auto;
border-radius: 10rpx;
border: 1rpx solid #555;
}
/* 播放器部分 */
.player{
height: 112rpx;
display: flex;
flex-direction: row;
align-items: center;
background: chocolate;
}
.player>image{
width: 80rpx;
height: 80rpx;
margin-left: 15rpx;
border-radius: 10rpx;
border: 1px solid #333;
}
.player-control image{
width: 80rpx;
height: 80rpx;
}
.player-info{
flex: 1;
font-size: 10pt;
line-height: 38rpx;
margin-left: 20rpx;
}
.player-info-singer{
color: #555;
}
/* 实现播放器的样式 */
.content-play{
display: flex;
flex-direction: column;
height: 100%;
text-align: center;
justify-content: space-around;
}
.content-play-cover>image{
width: 320rpx;
height: 320rpx;
border-radius: 50%;
border: 1px solid #555;
animation: roateImage 10s linear infinite;
}
@keyframes roateImage{
from{
transform: rotate(0deg);
}
to{
transform: rotate(360deg);
}
}
/* 播放进度条的样式 */
.content-play-progress{
display: flex;
text-align: center;
margin: 0 35rpx;
font-size: 10pt;
align-items: center;
}
.content-play-progress>slider{
flex: 1;
}
.playlist-content{
display: flex;
flex-direction: column;
height: 100%;
}
.playlist-item{
display: flex;
height: 112rpx;
align-items: center;
border-bottom: 1px solid #555;
}
.playlist-item>image{
width: 80rpx;
height: 80rpx;
border-radius: 10rpx;
border: 1px solid #555;
margin-left: 15rpx;
}
.playlist-item-info{
flex: 1;
font-size: 10pt;
line-height: 38rpx;
margin-left: 20rpx;
padding: 0 5rpx;
}
.playlist-item-play{
font-size: 10pt;
color: #c25b5b;
margin-right: 20rpx;
}
pages/index/index1.wxml:
<view class="tab">
<view class="tab-item {{item ==0?'active':'' }}" data-item="0" bindtap="changeItem">音乐推荐</view>
<view class="tab-item {{item ==1?'active':'' }}" data-item="1" bindtap="changeItem">播放器</view>
<view class="tab-item {{item ==2?'active':'' }}" data-item="2" bindtap="changeItem">播放列表</view>
</view>
<!-- 正文信息-->
<view class="content">
<swiper current="{{item}}" bindchange="changeTab">
<swiper-item>
<include src="./info"></include>
</swiper-item>
<swiper-item>
<include src="./play"></include>
</swiper-item>
<swiper-item>
<include src="./playlist"></include>
</swiper-item>
</swiper>
</view>
<!-- 播放器-->
<view class="player">
<image src="{{currentplay.coverImage}}" />
<view class="player-info">
<view>{{currentplay.title}}</view>
<view class="player-info-singer">{{currentplay.singer}}</view>
</view>
<view class="player-control">
<image src="../images/01.png" />
<!-- 播放或暂停 -->
<image wx:if="{{state=='paused'}}" src="../images/02.png" bindtap="play" />
<image wx:if="{{state =='running'}}" src="../images/02stop.png" bindtap="pause" />
<!-- 切换到下一首 -->
<image src="../images/03.png" bindtap="next" />
</view>
</view>
pages/index/info.wxml:
<swiper class="content-info-side" indicator-dots="true" indicator-color="#eee" indicator-active-color="#ffffff">
<swiper-item>
<image src="../images/banner.jpg" mode="aspectFill"></image>
</swiper-item>
<swiper-item>
<image src="../images/banner.jpg" mode="aspectFill"></image>
</swiper-item>
<swiper-item>
<image src="../images/banner.jpg" mode="aspectFill"></image>
</swiper-item>
</swiper>
<!--功能按钮功能区域-->
<view class="content-info-portal">
<view>
<image src="../images/04.png"></image>
<text>私人FM</text>
</view>
<view>
<image src="../images/05.png"></image>
<text>每日歌曲推荐</text>
</view>
<view>
<image src="../images/06.png"></image>
<text>云音乐新歌榜</text>
</view>
</view>
<!--推荐歌曲区域-->
<view class="content-info-list">
<text>推荐歌曲</text>
<view class="list-inner">
<view class="list-item">
<image src="../images/cover.jpg"></image>
<text>紫罗兰</text>
</view>
<view class="list-item">
<image src="../images/cover.jpg"></image>
<text>欢乐颂</text>
</view>
<view class="list-item">
<image src="../images/cover.jpg"></image>
<text>再见</text>
</view>
<view class="list-item">
<image src="../images/cover.jpg"></image>
<text>紫罗兰</text>
</view>
<view class="list-item">
<image src="../images/cover.jpg"></image>
<text>紫罗兰</text>
</view>
<view class="list-item">
<image src="../images/cover.jpg"></image>
<text>紫罗兰</text>
</view>
</view>
</view>
pages/index/play.wxml:文章来源:https://www.toymoban.com/news/detail-448481.html
<view class="content-play">
<!-- 显示播放信息 -->
<view>
<view>肖邦的夜曲</view>
<view>--肖邦--</view>
</view>
<view class="content-play-cover">
<image src="../images/cover.jpg" style="animation-play-state: {{state}};" />
</view>
<view class="content-play-progress">
<text>{{currentplay.currentTime}}</text>
<slider activeColor="#555" backgroundColor="#e9e9e9" block-size="12" block-color="#e9e9e9" value="80" bindchange="testBind" bindchanging="testBinding"></slider>
<text>{{currentplay.duration}}</text>
</view>
</view>
pages/index/playlist.wxml:文章来源地址https://www.toymoban.com/news/detail-448481.html
<view class="playlist-content">
<label wx:for="{{playlist}}" wx:key="id">
<view class="playlist-item" data-index="{{index}}" bindtap="changeMusic">
<!-- <image src="../images/cover.jpg" /> -->
<image src="{{item.coverImage}}"></image>
<view class="playlist-item-info">
<!-- <view>肖邦的夜曲</view> -->
<view>{{item.title}}</view>
<view>{{item.singer}}</view>
</view>
<view class="playlist-item-play" wx:if="{{index==playindex}}">
正在播放
</view>
</view>
</label>
</view>
到了这里,关于音乐播放器微信小程序的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!