《微信小程序》音乐播放器项目

音乐播放器项目

需求:在装有node.js的机器上使用微信开发者工具开发一个音乐播放项目

写这个项目的时候电脑前后蓝屏了5次,制作不易,希望大佬们给个双击,顺子在这感谢啦!

展示:
在这里插入图片描述

pages–>index–>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: 'See You Again',
      singer: 'Khalifa_Charlie Puth',
      src: 'http://localhost:3000/2.mp3',
      coverImgUrl: '/images/cover.jpg'
    }, {
    
    
      id: 3,
      title: '情字最大',
      singer: '平生青崖',
      src: 'http://localhost:3000/3.mp3',
      coverImgUrl: '/images/cover.jpg'
    }, {
    
    
      id: 4,
      title: '那年 · 年少',
      singer: '李宇宁',
      src: 'http://localhost:3000/4.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()
  }
})

在这里插入图片描述

{
    
    
  "navigationBarBackgroundColor": "#fff",
  "navigationBarTitleText": "音乐",
  "navigationBarTextStyle": "black"
}

在这里插入图片描述

<!-- 标签页标题 -->
<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/banner2.jpg" />
          </swiper-item>
          <swiper-item>
            <image src="/images/banner3.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/cover1.png" />
              <view>汇电音之经典领电音之奥妙
            </view>
            </view>
            <view class="list-item">
              <image src="/images/cover2.png" />
              <view>[周杰伦]每首歌曲,都是顶级文案
              </view>
            </view>
            <view class="list-item">
              <image src="/images/cover3.png" />
              <view>伤感情歌|不眠夜里的孤单心事
              </view>
            </view>
            <view class="list-item">
              <image src="/images/cover4.png" />
              <view>[经典]听这些怀旧的歌,体会经典的旋律
              </view>
            </view>
            <view class="list-item">
              <image src="/images/cover5.png" />
              <view>[粤语经典]漫漫人生路、每到离别总是伤
              </view>
            </view>
            <view class="list-item">
              <image src="/images/cover6.png" />
              <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>

在这里插入图片描述

page {
    
    
  display: flex;
  flex-direction: column;
  background: #17181a;
  color: #ccc;
  height: 100%;
}

.tab {
    
    
  display: flex;
}

.tab-item {
    
    
  flex: 1;
  font-size: 10pt;
  text-align: center;
  line-height: 72rpx;
  border-bottom: 6rpx solid #eee;
}

.content {
    
    
  flex: 1;
}

.content > swiper {
    
    
  height: 100%;
}

.player {
    
    
  background: #222;
  border-top: 1px solid #252525;
  height: 112rpx;
}

.tab-item.active {
    
    
  color: #c25b5b;
  border-bottom-color: #c25b5b;
}

.content-info {
    
    
  height: 100%;
}

::-webkit-scrollbar {
    
    
  width: 0;
  height: 0;
  color: transparent;
}

/* 轮播图 */

.content-info-slide {
    
    
  height: 302rpx;
  margin-bottom: 20px;
}

.content-info-slide image {
    
    
  width: 100%;
  height: 100%;
}

/* 功能按钮 */

.content-info-portal {
    
    
  display: flex;
  margin-bottom: 15px;
}

.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;
}

/* 热门音乐 */

.content-info-list {
    
    
  font-size: 11pt;
  margin-bottom: 20rpx;
}

.content-info-list > .list-title {
    
    
  margin: 20rpx 35rpx;
}

.content-info-list > .list-inner {
    
    
  display: flex;
  flex-wrap: wrap;
  margin: 0 20rpx;
}

.content-info-list > .list-inner > .list-item {
    
    
  flex: 1;
}

.content-info-list > .list-inner > .list-item > image {
    
    
  display: block;
  width: 200rpx;
  height: 200rpx;
  margin: 0 auto;
  border-radius: 10rpx;
  border: 1rpx solid #555;
}

.content-info-list > .list-inner > .list-item > view {
    
    
  width: 200rpx;
  margin: 10rpx auto;
  font-size: 10pt;
}

/* 播放器 */

.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;
}

/* 底部播放器 */

.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;
}

/* 显示专辑页面样式 */

.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;
}

/* 播放列表 */

.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;
}

在这里插入图片描述

<!-- 内容滚动区域 -->
<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>

在这里插入图片描述

<!-- 播放器 -->
<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>

在这里插入图片描述

<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>

图片呢?

在这里插入图片描述

01.png

请添加图片描述
02.png

请添加图片描述
02stop.png

请添加图片描述

03.png

请添加图片描述
04.png

请添加图片描述
05.png

请添加图片描述
06.png

请添加图片描述
banner.jpg

请添加图片描述
banner2.jpg

请添加图片描述
banner3.jpg

请添加图片描述
cover.jpg

请添加图片描述
cover1.png

请添加图片描述
cover2.png

请添加图片描述
cover3.png

请添加图片描述
cover4.png

请添加图片描述
node.js模拟服务器很简单,我在这就不多赘述了。

如果有任何疑问可以评论区留言,由于私信的比较多,如果我超过1天没有回复,可以加我的QQ:1525104866 ,说明来意,大家共同交流进步!

猜你喜欢

转载自blog.csdn.net/qq_46144237/article/details/121080961