原生微信小程序云音乐项目总结

功能概述:实现了基本云音乐APP的功能。

三个tabBar页面:

首页:视频页:

个人中心:

其他功能页面

登录页: 每日推荐页:

播放歌曲:

 一、首页

         简单运用了swiper和scroll-view动态渲染数据。

二、视频页

        头部是一个搜索框,是一个假的静态,点击可以跳转到搜索页面。

 

        然后是一个横向的滚动区域的导航栏。

导航栏下面有红色的线,点哪个就给哪个item加样式,同时有过渡动画。

之后就是视频内容部分,这问题是通过video和image进行性能优化实现的,因为API返回的问题,可以看我之前发的文章CSDN,所以要曲线救国一下。下面的喜欢和评论数据是真实的,但是没有写具体的评论内容。

三、个人中心

        这是真实的网易云用户的信息,是我个人的,练习了拖动之类的操作

 下面的听歌排行也是真实的

 四、登录页

         这个登录也是调用了后端给的接口,先进行基本的前端验证(正则,空等)之后,再发请求。

 let {phone,password} = this.data;
    // 前端表单验证
    if(!phone){
      wx.showToast({
        title: '手机号不能为空傻瓜',
        icon:"none"
      })
      return ;
    }
    let phoneReg =  /0?(13|14|15|18|17)[0-9]{9}/
    if(!phoneReg.test(phone)){
      wx.showToast({
        title: '果然是个笨蛋,手机号都能输错',
        icon:"none"
      })
      return ;
    }
    if(!password){
      wx.showToast({
        title: '呆瓜密码不能为空',
        icon:"none"
      })
      return ;
    }

在这里就要注意,因为是网易云的真实接口,所以很多返回的数据都是需要携带用户信息的,所以封装请求的时候,如果是登录的请求的话,就要把返回的数据中的cookie存入本地,同时在之后,如果有cookie就要携带在请求头中一起发送。这个项目封装的很简单,也没有显示提示框什么的。也不像之前做的vue的电商项目那么复杂,大概就是这样。这里发请求的参数url,也是重新写在了另一个config.js中,方便更改,因为可以是localhost,或者是内网穿透后的地址,或者是自己的服务器url,都可以方便查找修改。

// 发送ajax请求
import config from './config'
export default (url,data={},method='GET')=>{
  return new Promise((resolve,reject)=>{
    wx.request({
      url:config.mobileHost + url,
      data,
      method,
      header:{
        // 发请求的时候加一个cookie的头
        cookie:wx.getStorageSync('cookies')?wx.getStorageSync('cookies').find(item=>item.indexOf('MUSIC_U') !== -1) : ''
      },
      success:(res)=>{
        // 当登录的时候,把cookie存入本地
        if(data.isLogin){
          wx.setStorage({
            key:'cookies',
            data:res.cookies
          })
        }
        resolve(res.data)
      },
      fail:(err)=>{
        reject(err)
      }
    })
  })
}

五、每日推荐页

        这个页面是这个项目中的重点,也是代码最多,细节最多的页面,后面像搜索后跳转到歌曲详情页,歌单什么的和这个都是大同小异,所以也没练。

        这个页面,视频中写的不是很完善,我也是把能完善的地方完善的一下,首先就是动态渲染,因为之前的请求中,在请求头中加了用户cookie,所以返回的推荐歌曲都是我自己的每日推荐。静态中有一个细节,就是一个上圆角边框要压在头部图片的上方。是这样子的一个效果。 ,但是这样会有一个bug,会影响下面scroll-view的区域的高度,要把样式改一下。否则旁边的滚动条有bug。

.listScroll {
  height: calc(100vh - 390rpx);

}

上面的日期也是实时的,使用new Date()获取的实时时间

 六、歌曲详情页

        页面是我写这个项目中学的最多的,之最的地方。一个听歌APP最核心的就是听歌了。

这里有最简单的动态渲染数据,改变页面名称,还有这个磁盘播放与停止的一个拟真黑胶唱片播放的一个效果。一个是摇杆的播放与停止的2D变换,并加过渡效果。由一个isplay变量来动态绑定class。

/* 摇杆 */
.needle {
  position: relative;
  z-index: 99;
  top: -40rpx;
  left: 60rpx;
  width: 192rpx;
  height: 274rpx;
  /* 改变旋转的中心 */
  transform-origin: 40rpx 0;
  transform: rotate(-25deg);
  transition: transform 1s;
}
/* 播放时的摇杆位置 */
.needleRotate {
  transform:rotate(3deg);
}

 还有一个就是磁盘的旋转动画效果。

/* 磁盘旋转动画 */
.discAnimation {
  animation:disc 3s linear infinite 1s;
}
@keyframes disc {
  from {
    transform:rotate(0);
  }
  to {
    transform:rotate(360deg)
  }
}

之后,最头疼的地方就是播放进度条了,这里是最为头疼的地方,页面结构是一个正在播放进度条的盒子压在总进度条盒子上,然后在监听音乐播放的回调中定时改变正在播放进度条的宽度,并且实时更新播放时间动态渲染。

 结构

 <!-- 音乐播放进度条 -->
  <view class="progressControl">
    <text>{{currentTime}}</text>
    <!-- 总进度条 -->
    <view class="barControl" bindtouchstart="changePlayProgress"  bindtouchmove="changePlayProgress" bindtouchend="changePlayProgressed">
      <!-- 正在播放的进度条 -->
      <view class="audio-currentTime-bar" style="width: {{currentWidth + 'rpx'}}" >
        <!-- 小圆球 -->
        <view class="audio-circle"></view>
      </view>
    </view>
    <text>{{durationTime}}</text>
  </view>

样式

/* 底部进度条 */
.progressControl {
  position: absolute;
  bottom: 200rpx;
  /* width: 640rpx; */
  width: 730rpx;
  height: 80rpx;
  line-height: 80rpx;
  display: flex;
}

.progressControl text {
  /* padding: 0 20rpx; */
  margin: 0 20rpx;
  color: #242525;
}

.barControl {
  position: relative;
  /* width: 480rpx; */
  width: 480rpx;
  height: 6rpx;
  background: rgba(0, 0, 0, 0.4);
  margin: auto;
}

.audio-currentTime-bar {
  position: absolute;
  top: 0;
  left: 0;
  z-index: 1;
  height: 6rpx;
  background: rgb(185, 128, 41);
  transition: width .1s linear;
}

.audio-circle {
  position: absolute;
  top: -3rpx;
  right: -12rpx;
  z-index: 2;
  width: 12rpx;
  height: 12rpx;
  border-radius: 50%;
  background: #fff;
}

js部分

this.backgroundAudioManager.onTimeUpdate(()=>{
      // 格式化时间
      let currentTime = moment(this.backgroundAudioManager.currentTime * 1000).format('mm:ss')
      // 算出进度条
      //  当前播放时间 / 总时间 = (*进度条*) / 总长度
      let currentWidth = this.backgroundAudioManager.currentTime * 480 / this.backgroundAudioManager.duration;

      this.setData({
        currentTime,
        currentWidth
      })
    })

 在js中,计算出进度条的长度:currentWidth,然后动态地改变样式即可。

//  当前播放时间 / 总时间 = (*进度条*) / 总长度

之后的拖拽进度条,同时要同步音乐播放的进度,这里是我走了不少弯路。完全是我自己用自己的方式摸索出来的。监听手指按下的方法,同时绑定给手指移动。

拿到点下的点,通过计算来先是限定区域,不能超过这个进度条,这里的单位转换很头疼,px,rpx。然后同进动态更新currentWidth改变进度条渲染,然后同时也要更新音乐的播放进度,拿到刚刚改好的进度条的宽度,由此可以根据总时长和进度条总宽度来计算出音乐的当前播放时间,并用小程序提供的AIP更改音乐播放的进度。

// 手指按下进度条
  changePlayProgress(e){
    // 手指按下的点(px)
    startX = e.touches[0].clientX;
    // 点下的点离最开始的点的距离(rpx)
    let currentWidth = (startX - 67.5) * 2;
    if(currentWidth > 480){
      currentWidth = 479
    }else if(currentWidth < 0){
      currentWidth = 0;
    }
    this.setData({
      currentWidth
    })
    this.changePlayProgressed();

  },
  // 手指结束后再同步音乐
  changePlayProgressed(){
    let { currentWidth , musicId } = this.data
    // 放下要播放
    // this.musicControl(true,musicId);
    // 同时音乐的播放也要同步
    let currentTime = currentWidth / 480 * this.backgroundAudioManager.duration;
    this.backgroundAudioManager.seek(currentTime);
  },

还有就是这里的音乐播放的状态不仅绑定在了页面数据,还绑定在了全局对象上。有app实例对象上。

// 全局数据
  globalData:{
    isMusicPlay:false,//是否有音乐正在播放
    musicId:''//正在播放的音乐id
  },

这个页面最后一部分,就是由下面的iconfont组成的控制部分了,这边最后一个播放列表我没做,但是都大差不差,我实现了单曲,随机,顺序播放(详情见我之前的一篇文章云音乐项目,切歌方式(顺序,随机,单曲),歌曲结束后控制下一首歌是哪一首_一叶障目ynvf的博客-CSDN博客),还有播放暂停,上一曲与下一曲(这个和播放方式,言而总之就是决定下一曲的是什么,所以都是通过标识实现还是看我之前的那个详细的文章)。

 七、搜索页

         这是最后一个页面了,这个页面的与我之前写的uni-app电商项目中的搜索页大差不差,所以点击跳转到歌曲详情页也就没写,但是单独的搜索页的功能还是很全的。

点击搜索,为空时,和有内容时后面会出来一个清空的小叉号。还有按取消就可以返回到上一个视频video页面。

 下面就是历史记录这一块,这一块视频中老师的功能并不全,包括为空的判断,然后点击这一个小气泡可以自动在input中显示。但是我给完善了,然后每一次搜索的记录也是unshift加在数组的第一个,还有我把存的数组限定在了6条,若再多就删除数组中最后一项,然后历史记录也是通过Storage存在本地的。

// 把搜索的关键词放入历史记录数据中
    let { historyList } = this.data;
    // 如果当前搜索的关键词不为空的话,则发请求并存入本地
    if(searchContent){
      // 如果搜索的内容有,则要先删除
      if(historyList.indexOf(searchContent) !== -1){
        historyList.splice(historyList.indexOf(searchContent),1)
      }
      historyList.unshift(searchContent);
      if(historyList.length>6){
        historyList.pop()
      }
    // 存入本地
      wx.setStorageSync('searchHistory',historyList)

后面的小垃圾桶也可以删除历史记录。

 然后就是模糊搜索返回的数据动态渲染上去。和热搜榜的实时动态数据。

        大概的功能就是这样,当然功能还不是很完善,但我觉得其他要完善的话,能练到的东西也都一样,所以把可以完善的小点完善了,这个项目我大多是自己的想法,虽然是看的视频,但是多是我自己用别的方式写的,在一些小细节上没有偷懒,与我之前做的vue的一个前后台项目,和一个uni-app的项目不一样,这个项目我加入了很多我自己的想法,实现方法也是不同的,比如说这个老师在写input输入的时候用的是节流,而我用的是防抖。在这点上,我觉得写项目是非常有用的,对我整个的一个项目编程的思想上有了很多的提升,不过因为疫情和学校的原因没有大四还没有开始找实习,导致真实的项目是怎样的我还是不了解,但是自学能写的也只能是这样了。

  • 1
    点赞
  • 34
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值