10.6 音乐播放页

最后我们完成音乐播放页面,在前文的基础上这部分的逻辑代码很好完成,我们将重点放在页面布局上,先看下我们希望达到的效果(图10-9)。

图10-9 播放页样图

这个页面分为3个部分:顶部信息栏(歌曲名/专辑名),中间的唱片图,以及底下的控制按钮。

首先是信息栏:

<view class="song-info">
      <text class="song-title">{{playingMusic.name}}</text>
      <text class="song-subtitle">
        <block wx:for="{{playingMusic.singer}}" wx:key="unique">
          <block wx-if="{{index!=0}}">*</block>{{item.name}}</block>
      </text>
    </view>

这部分很简单,与我们前面写过的类似,多个歌手之间用“*”分隔。格式文件为:

.song-info {
    width:100%;
    padding:30rpx;
    box-sizing:border-box;
    text-align:center;
}
.song-title {
    display:block;
    width:100%;
    color:#fff;
    font-size:36rpx;
    line-height:60rpx;
    overflow:hidden;
    white-space:nowrap;
    text-overflow:ellipsis;
}
.song-subtitle {
    display:block;
    width:100%;
    font-size:28rpx;
    line-height:40rpx;
    color:rgba(255,255,255,.6);
    overflow:hidden;
    white-space:nowrap;
    text-overflow:ellipsis;
}

然后是中间的图片,这部分我们以动画形式表现,让唱片一直旋转,先看布局文件:

<view class="cd-info">
      <view class="cd-gan"></view>
      <view class="cd-inner cd-animation">
        <image class="cd-img" src="{{playingMusic.img}}"></image>
      </view>
    </view>

“cd-gan”是唱片部分里白色的播放杆部分,“cd-inner”是唱片部分,在这里为它添加表示唱片的黑色背景,然后在里门用小一圈的“cd-img”来加载我们获取的网络图片。最后为整个唱片添加动画“cd-animation”。这些工作全部由格式文件完成。

.cd-info {
  position: relative;
  width: 100%;
  text-align: center;
  padding-top: 120rpx;
}

.cd-gan {
  position: absolute;
  left: 50%;
  margin-top: -80rpx;
  margin-left: -150rpx;
  display: block;
  width: 300rpx;
  height: 200rpx;
  background: url('../../resources/images/cd_g.png');
  background-size: cover;
  z-index: 10;
}

.cd-inner {
  position: relative;
  display: inline-block;
  z-index: 4;
  height: 500rpx;
  width: 500rpx;
  background: url('../../resources/images/cd_b.png');
  background-size: cover;
  text-align: center;
  padding-top: 100rpx;
  box-sizing: border-box;
}

.cd-animation {
  -webkit-animation: circle 10s infinite linear;
  animation: circle 10s infinite linear;
}

.cd-img {
  display: inline-block;
  width: 300rpx;
  height: 300rpx;
  border-radius: 50%;
}

@keyframes circle {
  0% {
    transform: rotate(0deg);
  }

  100% {
    transform: rotate(360deg);
  }
}

这里面大多数的代码相信大家已经很熟悉了,重点看一下“cd-animation”这一部分,这里加载了动画“circle”并设置了动画时长与无限循环,这样就实现了在音乐播放时,唱片一直旋转的效果。“circle”动画我们使用关键帧keyframes来实现。

完成这两部分后我们以一个view来包裹它们,确定它在页面的位置。

<view class="main-box">
    <view class="song-info">
      <text class="song-title">{{playingMusic.name}}</text>
      <text class="song-subtitle">
        <block wx:for="{{playingMusic.singer}}" wx:key="unique">
          <block wx-if="{{index!=0}}">*</block>{{item.name}}</block>
      </text>
    </view>
    <view class="cd-info">
      <view class="cd-gan"></view>
      <view class="cd-inner cd-animation">
        <image class="cd-img" src="{{playingMusic.img}}"></image>
      </view>
    </view>
  </view>
.main-box {
  position: absolute;
  top: 0;
  bottom: 308rpx;
  z-index: 3;
  width: 100%;
  background: rgba(0, 0, 0, 0.2);
}

接着我们完成底下的操作部分。

<view class="ctre-box">
    <view class="slider-box">
      <text class="slider-text st-l">{{currTimeStr}}</text>
      <slider class="slider-inner"></slider>
      <text class="slider-text st-r">{{musicTimeStr}}</text>
    </view>
    <view class="music-ctr">
      <block wx-if="{{playType==0}}">
        <view class="music-sort ms-loop" data-type="{{playType}}" bindtap="changePlayType"></view>
      </block>
      <block wx-if="{{playType==1}}">
        <view class="music-sort ms-shuffle" data-type="{{playType}}" bindtap="changePlayType"></view>
      </block>
      <block wx-if="{{playType==2}}">
        <view class="music-sort ms-one" data-type="{{playType}}" bindtap="changePlayType"></view>
      </block>
      <view class="mc-inner">
        <view class="mci-icon mci-prev"></view>
        <view class="mci-icon mci-play"></view>
        <view class="mci-icon mci-next"></view>
      </view>
      <view class="music-list-btn" bindtap="showPlayList"></view>
    </view>
  </view>

操作控制部分由最上边的进度条部分“slider-box”和底下的操作按钮“mucis-ctr”组成。进度条我们使用slider组件,两段用两个text组件来显示当前播放时间与总时长。操作按钮部分,首先是播放模式的按钮,根据playType的值,改变顺序/随机/单曲的播放模式并对应加载不同的图片。然后是3个按钮,分别表示前一首/播放/下一首。最后是显示播放列表的按钮。

格式文件为:

.slider-box {
  box-sizing: border-box;
  padding: 20rpx 130rpx;
}

.slider-text {
  position: absolute;
  display: block;
  width: 100rpx;
  height: 40rpx;
  line-height: 40rpx;
  font-size: 24rpx;
  color: #fff;
}

.st-l {
  left: 60rpx;
}

.st-r {
  top: 20rpx;
  right: 40rpx;
  text-align: right;
}

.slider-inner {
  width: 100%;
}
.ctre-box {
  height: 308rpx;
  position: absolute;
  bottom: 0;
  z-index: 3;
  width: 100%;
  background: rgba(0, 0, 0, 0.2);
}

.music-ctr {
  position: relative;
  padding: 20rpx 120rpx;
}

.music-sort {
  position: absolute;
  left: 20rpx;
  width: 108rpx;
  height: 108rpx;
}

.ms-loop {
  background: url("../../resources/images/play_icn_loop.png");
  background-size: cover;
}

.ms-one {
  background: url("../../resources/images/play_icn_one.png");
  background-size: cover;
}

.ms-shuffle {
  background: url("../../resources/images/play_icn_shuffle.png");
  background-size: cover;
}

.music-list-btn {
  position: absolute;
  top: 36rpx;
  right: 20rpx;
  width: 108rpx;
  height: 108rpx;
  background: url("../../resources/images/play_icn_src.png");
  background-size: cover;
}

.mc-inner {
  text-align: center;
}

.mci-icon {
  display: inline-block;
  width: 142rpx;
  height: 142rpx;
}

.mci-prev {
  background: url("../../resources/images/play_btn_prev.png");
  background-size: cover;
}

.mci-play {
  background: url("../../resources/images/play_btn_play.png");
  background-size: cover;
}

.mci-pause {
  background: url("../../resources/images/play_btn_pause.png");
  background-size: cover;
}

.mci-next {
  background: url("../../resources/images/play_btn_next.png");
  background-size: cover;
}

最后写一下播放列表的布局:

<view class="play-list" hidden="{{showPlayList}}">
    <view class="play-list-header">
      <text>播放列表(185)</text>
      <text class="play-list-clear">清空</text>
    </view>
    <view class="play-list-inner">
      <block wx:for="{{playList}}" wx:key="unique">
        <view class="play-item">
          {{item.name}}
        </view>
      </block>
    </view>
    <view class="play-list-bottom" bindtap="closePlayList">关闭</view>
  </view>

格式文件为:

.play-list {
  position: absolute;
  top: 20%;
  bottom: 0;
  left: 0;
  width: 100%;
  z-index: 99;
  background: rgba(255, 255, 255, 0.95);   
}

.play-list-header {
  line-height: 88rpx;
  font-size: 32rpx;
  text-align: center;
  border-bottom: 2rpx solid rgba(0, 0, 0, 0.1);
}

.play-list-clear {
  position: absolute;
  right: 30rpx;
  font-size: 28rpx;
  color: rgba(0, 0, 0, 0.6);
}

.play-list-bottom {
  position: absolute;
  width: 100%;
  bottom: 0;
  height: 100rpx;
  line-height: 100rpx;
  text-align: center;
  font-size: 32rpx;
  border-top: 2rpx solid rgba(0, 0, 0, 0.1);
}

.play-list-inner {
  position: absolute;
  top: 90rpx;
  bottom: 102rpx;
  width: 100%;
  overflow-x: hidden;
  overflow-y: auto;
  padding-left: 20rpx;
}

.play-item {
  position: relative;
  widows: 100%;
  box-sizing: border-box;
  padding-right: 90rpx;
  height: 88rpx;
  line-height: 88rpx;
  font-size: 30rpx;
  border-bottom: 2rpx solid rgba(0, 0, 0, 0.1);
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

这里使用“z-index: 99;background: rgba(255, 255, 255, 0.95);”使播放列表覆盖部分音乐播放页面且背景半透明。

最后我们使用一个view来为整个页面加载背景,这个背景为我们获取的图片加上模糊效果。最后用一个view包裹所有布局。

<view class="play-view">
   ...
   <view class="bg blur" style="background-image:url('{{playingMusic.img}}');"></view>
</view>

使用格式文件添加模糊效果:

.paly-view {
  display: block;
  position: relative;
  width: 100%;
  height: 100%;
  overflow: hidden;
}

.blur {
  filter: blur(80rpx);
}

.bg {
  position: absolute;
  left: 0;
  right: 0;
  top: 0;
  bottom: 0;
  background-size: cover;
  background-position: bottom center;
}

最后我们加载数据:

var app = getApp()

Page({
    data: {
        playList: [],
        playIndex: 0,
        showPlayList: true,
        playingMusic: {},
        musicTime: 0,
        currTime: 0,
        musicTimeStr: 0,
        currTimeStr: 0,
        isPlay: false,
        playInv: 0,
        playPro: '',
        playType: 1
    },
    onLoad: function (options) {
        // 页面初始化 options为页面跳转所带来的参数
        var self = this;
        var list = app.globalData.playList;
        var playingMusic = null;
        if (list.length) {
            var index = app.globalData.playIndex;
            index = (list.length - 1 < index) ? list.length - 1 : index;
            playingMusic = list[index];
            this.setData({
                playList: list,
                playIndex: index,
                playingMusic: playingMusic
            });
        }
        wx.playBackgroundAudio({
            dataUrl: list[index].url,
            title: list[index].title,
            coverImgUrl: list[index].img,
            success: function () {
            },
            fail: function () {
                console.log('播放失败!');
            }
        });
    },
    changePlayType: function (e) {
        var dataSet = e.currentTarget.dataset;
        if (dataSet.type == 1) {
            this.setData({
                playType: 2
            });
        }
        if (dataSet.type == 2) {
            this.setData({
                playType: 0
            });
        }
        if (dataSet.type == 0) {
            this.setData({
                playType: 1
            });
        }
    },
    closePlayList: function (e) {
        this.setData({
            showPlayList: true
        })
    },
    showPlayList: function (e) {
        this.setData({
            showPlayList: false
        })
    },
    //三个按钮的点击事件
    pauseMusic: function () {
    },
    playNextMusic: function () {
    },
    playPreMusic:function(){
    },
})

results matching ""

    No results matching ""