音乐播放器实现介绍

目录

第1节 学习目标

第2节 开发准备

第3节 具体实现步骤


第1节 学习目标

1.1、标签页切换

1.2、音乐推荐

1.3、播放器

第2节 开发准备

2.1、了解项目最终效果

 

2.2、项目分析

2.2.1 小程序项目页面布局结构图

2.2.2 小程序项目目录结构

 2.2.3 项目页面初始化index

第3节 具体实现步骤

3.1 标签页切换实现步骤

3.1.1 任务分析:标签页和页面info.wxmlplay.wxmlpalylist.wxml)结构图

3.1.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事件

3.1.3 swiper组件编写滑动页面结构

 3.1.4 swiper组件编写滑动页面结构-index.wxss

 3.1.5 分析小程序页面布局

3.1.6 音乐小程序基础页面和样式tab导航效果

 <!--HTML 标签页标题 -->
<view class="tab">
  <view class="tab-item {{tab==0?'active':''}}" bindtap="changeItem" data-item="0">音乐推荐</view>
  <view class="tab-item {{tab==1?'active':''}}" bindtap="changeItem" data-item="1">播放器</view>
  <view class="tab-item {{tab==2?'active':''}}" bindtap="changeItem" data-item="2">播放列表</view>
</view>
/* CSS */
page {
     display: flex;
     flex-direction: column;
     background: #17181a;
     color: #ccc;
     height: 100%;
    }

3.1.7 实现标签页切换——滚动事件实现

 <swiper current="{{item}}" bindchange="changeTab">
        <swiper-item>
      <include src="../index/info"></include>
        </swiper-item>
        <swiper-item>
   <include src="../index/play"></include>
        </swiper-item>
        <swiper-item>
 <include src="../index/playlist"></include>
        </swiper-item>
    </swiper>

 

 3.2 实现音乐推荐页面

3.2.1 任务分析——音乐推荐页面结构图

 

 3.2.2 scroll-view组件的属性及说明

可选值

说明

默认

scroll-x

Boolean

允许横向滚动,默认为false

scroll-y

Boolean

允许纵向滚动,默认为false

scroll-top

Number / String

设置竖向滚动条的位置

scroll-left

Number / String

设置横向滚动条的位置

bindscrolltoupper

EventHandle

滚动到顶部/左边时触发的事件

bindscrolltolower

EventHandle

滚动到底部/右边时触发的事件

scroll-with-animation

Boolean

在设置滚动条位置时是否使用动画过渡

scroll-into-view

String

设置哪个方向可滚动,则在哪个方向滚动到该元素,

值应为某子元素idid不能以数字开头)

bindscroll

EventHandle

滚动时触发的事件

3.2.3 scroll-view组件对象

 3.2.4 scroll-view组件事件对象参数分析:

scrollLeft :横向滚动条左侧到视图左边的距离。
scrollTop :纵向滚动条上端到视图顶部的距离。
scrollHeight :纵向滚动条在 Y 轴上最大滚动距离。
scrollWidth :横向滚动条在 X 轴上最大的滚动距离。
deltaX :横向滚动条的滚动状态。
deltaY :纵向滚动条的滚动状态

3.2.5 常见image组件属性及说明:

可选值

说明

scaleToFill

不保持纵横比缩放图片,使图片的宽高完全拉伸至填满image元素。

适用于容器与图片宽高比相同的情况,如果不同,图片会变形。

aspectFit

保持纵横比缩放图片,使图片的长边能完全显示出来。

适用于将图片完整显示出来。

例如,详情页的图片

aspectFill

保持纵横比缩放图片,只保证图片的短边能完全显示出来,

长边将会发生截取。适用于容器固定,图片自动缩放的情况,

如列表页的缩略图

widthFix

宽度不变,高度自动变化,保持原图宽高比不变

top

不缩放图片,只显示图片的顶部区域

bottom

不缩放图片,只显示图片的底部区域

center

不缩放图片,只显示图片的中间区域

left

不缩放图片,只显示图片的左边区域

right

不缩放图片,只显示图片的右边区域

top left

不缩放图片,只显示图片的左上边区域

top right

不缩放图片,只显示图片的右上边区域

bottom left

不缩放图片,只显示图片的左下边区域

bottom right

不缩放图片,只显示图片的右下边区域

3.2.6 音乐推荐页面info.wxml

<!-- 内容滚动区域 -->
<scroll-view class="content-info" scroll-y>
  <!-- 轮播图 -->
  <swiper class="content-info-slide" indicator-color="rgba(255,255,255,.5)" indicator-active-color="#fff" indicator-dots circular autoplay>
    <swiper-item>
      <image src="/images/banner.jpg" />
    </swiper-item>
    <swiper-item>
      <image src="/images/banner.jpg" />
    </swiper-item>
    <swiper-item>
      <image src="/images/banner.jpg" />
    </swiper-item>
  </swiper>
  <!-- 功能按钮 -->
  <view class="content-info-portal">
    <view>
      <image src="/images/04.png" />
      <text>私人FM</text>
    </view>
    <view>
      <image src="/images/05.png" />
      <text>每日歌曲推荐</text>
    </view>
    <view>
      <image src="/images/06.png" />
      <text>云音乐新歌榜</text>
    </view>
  </view>
  <!-- 热门音乐 -->
  <view class="content-info-list">
    <view class="list-title">推荐歌曲</view>
    <view class="list-inner">
      <view class="list-item">
        <image src="/images/cover.jpg" />
        <view>紫罗兰</view>
      </view>
      <view class="list-item">
        <image src="/images/cover.jpg" />
        <view>五月之歌</view>
      </view>
      <view class="list-item">
        <image src="/images/cover.jpg" />
        <view>菩提树</view>
      </view>
      <view class="list-item">
        <image src="/images/cover.jpg" />
        <view>欢乐颂</view>
      </view>
      <view class="list-item">
        <image src="/images/cover.jpg" />
        <view>安魂曲</view>
      </view>
      <view class="list-item">
        <image src="/images/cover.jpg" />
        <view>摇篮曲</view>
      </view>
    </view>
  </view>
</scroll-view>

3.2.7 底部播放页面index.wxml和播放样式index.wxss

<!-- 底部播放器 -->
<view class="player">
  <image class="player-cover" src="{{play.coverImgUrl}}" />
  <view class="player-info">
    <view class="player-info-title">{{play.title}}</view>
    <view class="player-info-singer">{{play.singer}}</view>
  </view>
  <view class="player-controls">
    <!-- 切换到播放列表 -->
    <image src="/images/01.png" bindtap="changePage" data-page="2" />
    <!-- 播放或暂停 -->
    <image wx:if="{{state=='paused'}}" src="/images/02.png" bindtap="play" />
    <image wx:else src="/images/02stop.png" bindtap="pause" />
    <!-- 下一曲 -->
    <image src="/images/03.png" bindtap="next" />
  </view>
</view>
/* 底部播放器 */

.player {
  display: flex;
  align-items: center;
  background: #222;
  border-top: 1px solid #252525;
  height: 112rpx;
}

.player-cover {
  width: 80rpx;
  height: 80rpx;
  margin-left: 15rpx;
  border-radius: 8rpx;
  border: 1px solid #333;
}

.player-info {
  flex: 1;
  font-size: 10pt;
  line-height: 38rpx;
  margin-left: 20rpx;
  padding-bottom: 8rpx;
}

.player-info-singer {
  color: #888;
}

.player-controls image {
  width: 80rpx;
  height: 80rpx;
  margin-right: 15rpx;
}

3.2.8 页面推荐最终效果

 3.3 播放器的实现

3.3.1 任务分析——音乐播放器页面结构图

 3.3.2 播放器的具体功能进行分析

音乐信息 :显示当前播放曲目的标题和艺术家。
专辑封面 :当音乐播放时,专辑封面会顺时针旋转。
播放进度 显示 播放进度 调节音乐进度

3.3.3 音频API接口的方法及说明:

可选值

名称

说明

方法

onPause()

音频暂停事件(参数为回调函数)

onStop()

音频停止事件(参数为回调函数)

onEnded()

音频自然播放至结束的事件(参数为回调函数)

onSeeked()

音频进行跳转操作的事件(参数为回调函数)

onTimeUpdate()

音频播放进度更新事件(参数为回调函数)

onError()

音频播放错误事件(参数为回调函数)

3.3.4 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

拖动过程中触发的事件

3.3.5 实现音乐播放功能

 

3.3.6 播放器页面编写:play.wxml和index.wxss

<!-- 播放器 -->
<view class="content-play">
  <!-- 显示音乐信息 -->
  <view class="content-play-info">
    <text>{{play.title}}</text>
    <view>—— {{play.singer}} ——</view>
  </view>
  <!-- 显示专辑封面 -->
  <view class="content-play-cover">
    <image src="{{play.coverImgUrl}}" style="animation-play-state:{{state}}" />
  </view>
  <!-- 显示播放进度和时间 -->
  <view class="content-play-progress">
    <text>{{play.currentTime}}</text>
    <view>
      <slider bindchange="sliderChange" activeColor="#d33a31" block-size="12" backgroundColor="#dadada" value="{{play.percent}}" />
    </view>
    <text>{{play.duration}}</text>
  </view>
</view>
.content-play {
  display: flex;
  justify-content: space-around;
  flex-direction: column;
  height: 100%;
  text-align: center;
}

.content-play-info > view {
  color: #888;
  font-size: 11pt;
}
/* 显示专辑页面样式 */

.content-play-cover image {
  animation: rotateImage 10s linear infinite;
  width: 400rpx;
  height: 400rpx;
  border-radius: 50%;
  border: 1px solid #333;
}

@keyframes rotateImage {
  from {
    transform: rotate(0deg);
  }

  to {
    transform: rotate(360deg);
  }
}

/* 播放进度和时间 */

.content-play-progress {
  display: flex;
  align-items: center;
  margin: 0 35rpx;
  font-size: 9pt;
  text-align: center;
}

.content-play-progress > view {
  flex: 1;
}

3.3.7 播放器实现效果

3.4 音乐播放列表

3.4.1 任务分析——播放列表页面布局分析

 3.4.2 播放列表页面编写playList.wxml

<scroll-view class="content-playlist" scroll-y>
  <view class="playlist-item" wx:for="{{playlist}}" wx:key="id" bindtap="change" data-index="{{index}}">
    <image class="playlist-cover" src="{{item.coverImgUrl}}" />
    <view class="playlist-info">
      <view class="playlist-info-title">{{item.title}}</view>
      <view class="playlist-info-singer">{{item.singer}}</view>
    </view>
    <view class="playlist-controls">
      <text wx:if="{{index==playIndex}}">正在播放</text>
    </view>
  </view>
</scroll-view>

3.4.3 播放列表样式编写index.wxss

/* 播放列表 */

.playlist-item {
  display: flex;
  align-items: center;
  border-bottom: 1rpx solid #333;
  height: 112rpx;
}

.playlist-cover {
  width: 80rpx;
  height: 80rpx;
  margin-left: 15rpx;
  border-radius: 8rpx;
  border: 1px solid #333;
}

.playlist-info {
  flex: 1;
  font-size: 10pt;
  line-height: 38rpx;
  margin-left: 20rpx;
  padding-bottom: 8rpx;
}

.playlist-info-singer {
  color: #888;
}

.playlist-controls {
  font-size: 10pt;
  margin-right: 20rpx;
  color: #c25b5b;
}

3.4.4 播放列表效果图

 3.5 完整index.wxml

<!-- 标签页标题 -->
<view class="tab">
  <view class="tab-item {{tab==0?'active':''}}" bindtap="changeItem" data-item="0">音乐推荐</view>
  <view class="tab-item {{tab==1?'active':''}}" bindtap="changeItem" data-item="1">播放器</view>
  <view class="tab-item {{tab==2?'active':''}}" bindtap="changeItem" data-item="2">播放列表</view>
</view>
<!-- 内容区域 -->
<view class="content">
  <swiper current="{{item}}" bindchange="changeTab">
    <swiper-item>
      <!-- 内容滚动区域 -->
      <scroll-view class="content-info" scroll-y>
        <!-- 轮播图 -->
        <swiper class="content-info-slide" indicator-color="rgba(255,255,255,.5)" indicator-active-color="#fff" indicator-dots circular autoplay>
          <swiper-item>
            <image src="/images/banner.jpg" />
          </swiper-item>
          <swiper-item>
            <image src="/images/banner.jpg" />
          </swiper-item>
          <swiper-item>
            <image src="/images/banner.jpg" />
          </swiper-item>
        </swiper>
        <!-- 功能按钮 -->
        <view class="content-info-portal">
          <view>
            <image src="/images/04.png" />
            <text>私人FM</text>
          </view>
          <view>
            <image src="/images/05.png" />
            <text>每日歌曲推荐</text>
          </view>
          <view>
            <image src="/images/06.png" />
            <text>云音乐新歌榜</text>
          </view>
        </view>
        <!-- 热门音乐 -->
        <view class="content-info-list">
          <view class="list-title">推荐歌曲</view>
          <view class="list-inner">
            <view class="list-item">
              <image src="/images/cover.jpg" />
              <view>紫罗兰</view>
            </view>
            <view class="list-item">
              <image src="/images/cover.jpg" />
              <view>五月之歌</view>
            </view>
            <view class="list-item">
              <image src="/images/cover.jpg" />
              <view>菩提树</view>
            </view>
            <view class="list-item">
              <image src="/images/cover.jpg" />
              <view>欢乐颂</view>
            </view>
            <view class="list-item">
              <image src="/images/cover.jpg" />
              <view>安魂曲</view>
            </view>
            <view class="list-item">
              <image src="/images/cover.jpg" />
              <view>摇篮曲</view>
            </view>
          </view>
        </view>
      </scroll-view>
    </swiper-item>
    <swiper-item>
      <!-- 播放器页面 -->
      <include src="play.wxml" />
    </swiper-item>
    <swiper-item>
      <include src="playlist.wxml" />
    </swiper-item>
  </swiper>
</view>
<!-- 底部播放器 -->
<view class="player">
  <image class="player-cover" src="{{play.coverImgUrl}}" />
  <view class="player-info">
    <view class="player-info-title">{{play.title}}</view>
    <view class="player-info-singer">{{play.singer}}</view>
  </view>
  <view class="player-controls">
    <!-- 切换到播放列表 -->
    <image src="/images/01.png" bindtap="changePage" data-page="2" />
    <!-- 播放或暂停 -->
    <image wx:if="{{state=='paused'}}" src="/images/02.png" bindtap="play" />
    <image wx:else src="/images/02stop.png" bindtap="pause" />
    <!-- 下一曲 -->
    <image src="/images/03.png" bindtap="next" />
  </view>
</view>

3.6 完整index.js

// pages/index/index.js
Page({

  /**
   * 页面的初始数据
   */
  data: {
    item: 0,
    tab: 0,
    // 播放列表数据
    playlist: [{
      id: 1,
      title: '钢琴协奏曲',
      singer: '肖邦',
      src: 'http://localhost:3000/1.mp3',
      coverImgUrl: '/images/cover.jpg'
    }, {
      id: 2,
      title: '奏鸣曲',
      singer: '莫扎特',
      src: 'http://localhost:3000/2.mp3',
      coverImgUrl: '/images/cover.jpg'
    }, {
      id: 3,
      title: '欢乐颂',
      singer: '贝多芬',
      src: 'http://localhost:3000/1.mp3',
      coverImgUrl: '/images/cover.jpg'
    }, {
      id: 4,
      title: '爱之梦',
      singer: '李斯特',
      src: 'http://localhost:3000/2.mp3',
      coverImgUrl: '/images/cover.jpg'
    }],
    state: 'paused',
    playIndex: 0,
    play: {
      currentTime: '00:00',
      duration: '00:00',
      percent: 0,
      title: '',
      singer: '',
      coverImgUrl: '/images/cover.jpg',
    }
  },

  // 页面切换
  changeItem: function(e) {
    this.setData({
      item: e.target.dataset.item,
    })
  },
  // tab切换
  changeTab: function(e) {
    this.setData({
      tab: e.detail.current
    })
  },

  // 实现播放器播放功能
  audioCtx: null,
  onReady: function() {
    this.audioCtx = wx.createInnerAudioContext()
    // 默认选择第1曲
    this.setMusic(0)
    var that = this
    // 播放进度检测
    this.audioCtx.onError(function() {
      console.log('播放失败:' + that.audioCtx.src)
    })
    // 播放完成自动换下一曲
    this.audioCtx.onEnded(function() {
      that.next()
    })
    // 自动更新播放进度
    this.audioCtx.onPlay(function() {})
    this.audioCtx.onTimeUpdate(function() {
      that.setData({
        'play.duration': formatTime(that.audioCtx.duration),
        'play.currentTime': formatTime(that.audioCtx.currentTime),
        'play.percent': that.audioCtx.currentTime / that.audioCtx.duration * 100
      })
    })
    // 格式化时间
    function formatTime(time) {
      var minute = Math.floor(time / 60) % 60;
      var second = Math.floor(time) % 60
      return (minute < 10 ? '0' + minute : minute) + ':' + (second < 10 ? '0' + second : second)
    }
  },
  // 音乐播放
  setMusic: function(index) {
    var music = this.data.playlist[index]
    this.audioCtx.src = music.src
    this.setData({
      playIndex: index,
      'play.title': music.title,
      'play.singer': music.singer,
      'play.coverImgUrl': music.coverImgUrl,
      'play.currentTime': '00:00',
      'play.duration': '00:00',
      'play.percent': 0
    })
  },

  // 播放按钮
  play: function() {
    this.audioCtx.play()
    this.setData({
      state: 'running'
    })
  },

  // 暂停按钮
  pause: function() {
    this.audioCtx.pause()
    this.setData({
      state: 'paused'
    })
  },

  // 下一曲按钮
  next: function() {
    var index = this.data.playIndex >= this.data.playlist.length - 1 ? 0 : this.data.playIndex + 1
    this.setMusic(index)
    if (this.data.state === 'running') {
      this.play()
    }
  },
  
  // 滚动条调节歌曲进度
  sliderChange: function(e) {
    var second = e.detail.value * this.audioCtx.duration / 100
    this.audioCtx.seek(second)
  },

  // 播放列表换曲功能
  change: function(e) {
    this.setMusic(e.currentTarget.dataset.index)
    this.play()
  }
})

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值