雁过留声 发表于 2022-6-25 00:15:08

【微信小程序学习】网易云音乐歌曲详情页代码实现

这里记录一下做网易云小程序的音乐播放详情页面的代码。
音乐播放界面的主要的重点有几个:
  1、磁盘和摇杆的旋转效果,这里运用了css的动画属性
  2、音乐播放和暂停,下一首/上一首等播放效果的实现
  3、进度条的样式和控制
  4、和上一页音乐推荐列表页通信,利用订阅与发布Pubsub
https://img-blog.csdnimg.cn/78ad1f21986e4040830115ed2ee955ff.png
   HTML代码及要点
<view class="songDetailContainer">
<view class="author">{{song.ar.name}}</view>
<view class="circle"></view>
<image class="needle {{isPlay?'needleRotate':''}}" src="/static/images/song/needle.png"></image>

<view class="discContainer {{isPlay?'discAnimation':''}}">
   <image class="disc" src="/static/images/song/disc.png"></image>
   <image class="musicImg" src="{{song.al.picUrl}}"></image>
</view>


<view class="progressControl">
    <text>{{currentTime}}</text>
   
    <view class="barControl">
      
      <view class="audio-currentTime-Bar" style="width: {{currentWidth + 'rpx'}}">
      
      <view class="audio-circle"></view>
      </view>
    </view>
    <text>{{durationTime}}</text>
</view>


<view class="musicControl">
    <text class="iconfont icon-iconsMusicyemianbofangmoshiShuffle"></text>

    <text class="iconfont icon-shangyishou" id="pre" bindtap="handleSwitch"></text>

    <text class="iconfont {{isPlay?'icon-zanting': 'icon-bofang'}} big" bindtap="handleMusicPlay"></text>

    <text class="iconfont icon-next" id="next" bindtap="handleSwitch"></text>

    <text class="iconfont icon-iconsMusicyemianbofangmoshiPlayList"></text>
</view>
</view> HTML要点: 
https://img-blog.csdnimg.cn/16e54a8c5c2a4cb181037006c46ffce7.png
https://img-blog.csdnimg.cn/ee9aeb395bc44390992d4f07c229589d.png
 https://img-blog.csdnimg.cn/165829af638445cc9f37a547d7acbc8f.png
这里利用了三元表达式,当isPlay为true时,摇杆、磁盘和播放按钮就会开始启动动画,否则相反。
https://img-blog.csdnimg.cn/34fd32ee068541b6a1efe4f22f307ba7.png
 实时进度条的动画利用了红色实时进度条的宽度的变化风格。
    CSS代码及要点
/* pages/songDetail/songDetail.wxss */
@import "/static/iconfont/iconfont.wxss";
page {
height: 100%;
}
.songDetailContainer{
height: 100%;
background: rgba(0,0,0,0.5);
display: flex;
flex-direction: column;
align-items: center;

}
/* 底座 */
.circle {
position: relative;
z-index: 100;
width: 60rpx;
height: 60rpx;
border-radius: 50%;
background: #fff;
margin: 10rpx 0;
}
/* 摇杆 */
.needle{
position: relative;
z-index: 99;
top:-40rpx;
left: 60rpx;
width:192rpx;
height:274rpx;
/* 要先设置好旋转的中心点 */
transform-origin:40rpx 0;
transform: rotate(-20deg);
transition: transform 1s;

}
/* 播放时摇杆动画 */
.needleRotate{
transform: rotate(0deg);
}

/* 磁盘 */
.discContainer{
position: relative;
top:-170rpx;
width: 598rpx;
height: 598rpx;
}

.discAnimation{
animation: disc 3s linear infinite;
animation-delay:1s;
}
/*
@keyframes:设置动画帧
1、from to
    使用于简单的动画,只有起始帧和结束帧

2、百分比
    多用于复杂的动画,动画不止两帧
*/
@keyframes disc{
from{
    transform: rotate(0deg);
}
to{
    transform: rotate(360deg);
}
}

.disc{
width: 598rpx;
height: 598rpx;
}
.musicImg{
position: absolute;
top:0;
right:0;
bottom:0;
left:0;
margin: auto;
width: 370rpx;
height: 370rpx;
border-radius: 50%;
}
/* 底部控制区域 */
.musicControl {
position: absolute;
bottom: 40rpx;
left: 0;
border-top: 1rpx solid #fff;
width: 100%;
display: flex;

}

.musicControltext {
width: 20%;
height: 120rpx;
line-height: 120rpx;
text-align: center;
color: #fff;
font-size: 50rpx;
}

.musicControltext.big{
font-size: 80rpx;
}

/* 进度条控制区域 */
.progressControl {
position: absolute;
bottom: 200rpx;
width: 640rpx;
height: 80rpx;
line-height: 80rpx;
display: flex;
}


.barControl {
position: relative;
width: 450rpx;
height: 4rpx;
background: rgba(0, 0, 0, 0.4);
margin: auto;
}

.audio-currentTime-Bar {
position: absolute;
top: 0;
left: 0;
z-index: 1;
height: 4rpx;
background: red;

}


/* 小圆球 */
.audio-circle {
position: absolute;
right: -12rpx;
top: -4rpx;
width: 12rpx;
height: 12rpx;
border-radius: 50%;
background: #fff;
} CSS要点: 
 https://img-blog.csdnimg.cn/5026185747524fda82f2d528b8bb3f8c.png
https://img-blog.csdnimg.cn/183cf69f52414e9498fd99dd54818a3b.png
这里利用了transform动画,首先设置好旋转的中心点,利用transform-origin属性, 上方图片红框代表摇杆图片的范围,蓝色点为需要旋转的中心点,位置为x坐标为40rpx,纵坐标为0。摇杆要从原来的图片位置逆时针转动20度,所以设定为transform:rotate(-20deg)。加上过渡效果,利用transition:transform 1s。
https://img-blog.csdnimg.cn/2c29de07d3594318aaea41b57d355c7d.png
磁盘的转动利用了css里的animation,linear代表线性,infinite代表一直动。
要设置动画帧@keyframes,从0度到360度,代表了磁盘的旋转。 
    JS代码及要点
// pages/songDetail/songDetail.js
import request from '../../../utils/request'
import PubSub from 'pubsub-js'
import moment from 'moment'
//获取全局实例
const appInstance = getApp();
Page({

/**
   * 页面的初始数据
   */
data: {
   isPlay:false,//播放状态
   song:{},//歌曲详情对象
   musicId:'', //音乐id
   musicLink:'',//音乐的链接
   currentTime:'00:00',//实时时间
   durationTime:'00:00',//总时长
   currentWidth:0, //实时进度条宽度
},

/**
   * 生命周期函数--监听页面加载
   */
onLoad: function (options) {
    //options:用于接收路由跳转的query参数
    //原生小程序中路由传参,对参数的长度有限制,如果长度过长会自动截取掉
   
    // console.log(options)
    // console.log(musicId)
    let musicId = options.musicId;
    this.setData({
      musicId
    })
    //获取音乐详情
    this.getMusicInfo(musicId);


    /**
   * 问题:如果用户操作系统的控制音乐播放/暂停的按钮,页面不知道,导致页面是否播放的状态和真实的音乐播放状态不一致
   * 解决方案:
   *   通过控制音频的实例backgroundAudioManager 去监视音乐暂停播放/暂停
   */

    //判断当前页面音乐是否在播放
    if(appInstance.globalData.isMusicPlay && appInstance.globalData.musicId
   === musicId){
       //修改当前页面音乐播放状态为true
       this.setData({
         isPlay:true
       })
    }
    //创建控制音乐播放的实例
    this.backgroundAudioManager = wx.getBackgroundAudioManager();
    //监视音乐播放/暂停/停止
    this.backgroundAudioManager.onPlay(()=>{
      //修改音乐是否播放的状态
      this.changePlayState(true);
      //修改全局音乐播放的状态
      appInstance.globalData.musicId = musicId;
    });
    this.backgroundAudioManager.onPause(() => {
      this.changePlayState(false);   
    });
    this.backgroundAudioManager.onStop(() => {
      this.changePlayState(false);   
    });
    //监听音乐自然播放结束
    this.backgroundAudioManager.onEnded(() => {
   //自动切换至下一首音乐,并且自动播放
      PubSub.publish('switchType','next')
   //将实时进度条还原成0
   this.setData({
       currentWidth:0,
       currentTime: '00:00'
   })

    })

    //监听音乐实时播放的进度
    this.backgroundAudioManager.onTimeUpdate(()=>{
      //格式化实时播放时间
      let currentTime = moment(this.backgroundAudioManager.currentTime*1000).format('mm:ss')
      let currentWidth = this.backgroundAudioManager.currentTime / this.backgroundAudioManager.duration*450
      this.setData({
      currentTime,
      currentWidth
      })
    })
},
//修改播放状态的功能函数
changePlayState(isPlay){
    this.setData({
      isPlay
    })
    //修改全局音乐播放的状态
    appInstance.globalData.isMusicPlay = isPlay;
},

//获取音乐详情的功能函数
async getMusicInfo(musicId){
    let songData = await request('/song/detail',{ids:musicId});
    //songData.songs.dt 单位ms
    let durationTime = moment(songData.songs.dt).format('mm:ss')
    this.setData({
      song:songData.songs,
      durationTime
    })
    //动态修改窗口标题
    wx.setNavigationBarTitle({
      title:this.data.song.name
    })

},
//点击播放/暂停的回调
handleMusicPlay(){
    let isPlay = !this.data.isPlay;
    // //修改是否播放的状态
    // this.setData({
    //   isPlay
    // })
    let {musicId,musicLink} = this.data;
    this.musicControl(isPlay,musicId,musicLink);
},

//控制音乐播放/暂停的功能函数
async musicControl(isPlay, musicId, musicLink){
   
      if(isPlay){//音乐播放
      if(!musicLink){
          //获取音乐播放链接
          let musicLinkData = await request('/song/url', { id: musicId });
          musicLink = musicLinkData.data.url;
          this.setData({
            musicLink
          })
      }
      
      this.backgroundAudioManager.src = musicLink;
      this.backgroundAudioManager.title = this.data.song.name;
   }else{//暂停音乐      
      this.backgroundAudioManager.pause();
   }
},

//点击切换上一首下一首的回调
handleSwitch(event){
    //获取切歌的类型
    let type = event.currentTarget.id;
    //关闭当前播放的音乐
    this.backgroundAudioManager.stop()
    //订阅来自recommendsong页面发布的musicId消息
    PubSub.subscribe('musicId',(msg,musicId)=>{
       // console.log(musicId)
   
    //获取音乐详情信息
    this.getMusicInfo(musicId)
    //自动播放切换的当前音乐
    this.musicControl(true,musicId)
    //取消订阅
    PubSub.unsubscribe('musicId')
    })
    //发布消息数据给recommendSong
    PubSub.publish('switchType',type)

},
}) JS要点: 
 全局数据放在app.js中:
https://img-blog.csdnimg.cn/ae16576a2356464599c8507916652580.png
 https://img-blog.csdnimg.cn/9fe8c4d56c124ac986e5f2730a11c7f7.png
这里利用了https://img-blog.csdnimg.cn/15e4afdd416c46a1824204bc802f7060.png 



免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!
页: [1]
查看完整版本: 【微信小程序学习】网易云音乐歌曲详情页代码实现