微信小程序【网易云音乐实战】(第五篇 转发分享、每日推荐、音乐播放、页面通信npm包、进度条、全局数据)

一、转发分享功能

onShareAppMessage(Object object)
在这里插入图片描述

在这里插入图片描述

Button
在这里插入图片描述
在这里插入图片描述

<button open-type="share" class="item btn">
    <text class="iconfont icon-gengduo"></text>
</button>
  /**
   * 用户点击右上角分享
   */
  onShareAppMessage: function ({
    
    from}) {
    
    
    // from为 menu表示页面转发,button表示按钮转发
    console.log(from);
    if(from === "button"){
    
    
      return {
    
    
        title:"来自button的转发",
        page:"/pages/video/video",
        imageUrl:"/static/images/nvsheng.jpg"
      }
    }else{
    
    
      return {
    
    
        title:"来自menu的转发",
        page:"/pages/video/video",
        imageUrl:"/static/images/nvsheng.jpg"
      }
    }
  }

在这里插入图片描述

如果要分享给小伙伴体验,需要在小程序的 成员管理 —> 添加体验成员


二、每日推荐歌曲

接口:
在这里插入图片描述

在这里插入图片描述

<view class="recommendSongContainer">
    <!--  头部  -->
    <view class="header">
        <image src="/static/images/recommendSong/recommendSong.jpg"></image>
        <view class="date">
            <text class="day">{
   
   {day}} / </text>
            <text class="month">{
   
   {month}}</text>
        </view>
    </view>

    <!--   列表区域 -->
    <view class="ListContainer">
        <view class="listHeader">
            <text>播放全部</text>
            <text class="changeMore">多选</text>
        </view>

        <!--   内容区     -->
        <scroll-view scroll-y class="listScroll">
            <view class="scrollItem" wx:for="{
     
     {recommendList}}" wx:key="id">
                <image src="{
     
     {item.album.picUrl}}"></image>
                <view class="musicInfo">
                    <text class="musicName">{
   
   {item.name}}</text>
                    <text class="author">{
   
   {item.artists[0].name}}</text>
                </view>
                <text class="iconfont icon-gengduo"></text>
            </view>
        </scroll-view>
    </view>

</view>

.recommendSongContainer .header{
    
    
    position: relative;
    width: 100%;
    height: 300rpx;
}

.recommendSongContainer .header image{
    
    
    width: 100%;
    height: 100%;
}

.recommendSongContainer .header .date{
    
    
    position: absolute;
    left: 50%;
    top: 50%;
    margin-left: -150rpx;
    margin-top: -50rpx;

    width: 300rpx;
    height: 100rpx;
    text-align: center;
    line-height: 100rpx;
    color: #FFF;
}

.header .date .day{
    
    
    font-size: 40rpx;
}

/* 列表区域的样式  */
.ListContainer{
    
    
    position: relative;
    top: -20rpx;
    padding: 0 20rpx;
    border-radius: 30rpx;
    background: #FFF;
}

.listHeader{
    
    
    height: 80rpx;
    line-height: 80rpx;
}

.listHeader .changeMore{
    
    
    float: right;
}

/* 列表内容区样式*/
.listScroll{
    
    
    width: 100%;
    height: calc(100vh - 380rpx);
}

.scrollItem{
    
    
    display: flex;
    position: relative;
    margin-bottom: 20rpx;
}

.scrollItem image{
    
    
    width: 80rpx;
    height: 80rpx;
    border-radius: 8rpx;
}

.musicInfo{
    
    
    display: flex;
    flex-direction: column;
    margin-left: 20rpx;
    max-width: 400rpx;
}

.musicInfo text{
    
    
    height: 40rpx;
    line-height: 40rpx;
    font-size: 24rpx;
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
}

.scrollItem .iconfont{
    
    
    position: absolute;
    right: 0;
    width: 80rpx;
    height: 80rpx;
    line-height: 80rpx;
    text-align: right;
}
  /**
   * 生命周期函数--监听页面加载
   */
  onLoad: function (options) {
    
    
    // 判断用户是否登录
    let userInfo = wx.getStorageSync("userInfo");
    if(!userInfo){
    
    
      wx.showToast({
    
    
        title:"请先登录",
        icon:"none",
        success:()=>{
    
    
          // 跳转到登录界面
          wx.reLaunch({
    
    
            url:"/pages/login/login"
          })
        }
      })
    }

    // 更新日期
    this.setData({
    
    
      day:new Date().getDate(),
      month:new Date().getMonth()+1
    });

    // 获取每日推荐的数据
    this.getRecommendList()
  },

  // 获取用户每日推荐数据
  async getRecommendList() {
    
    
    let recommendList = await request("/recommend/songs");
    this.setData({
    
    
      recommendList: recommendList.recommend
    })
  },

三、音乐播放

在这里插入图片描述

知识点:

旋转样式:

transform-origin: 40rpx 0; /* 旋转中心*/
transform: rotate(-20deg); /* 旋转角度*/
transition: transform 1s; /* 旋转过过渡动画 */

class的动态控制:

扫描二维码关注公众号,回复: 12426568 查看本文章
方式一:&&
<image class="needle {
     
     {isPlay && 'needleRotate'}}" src=""></image>
方式二:三元运算
<image class="needle {
     
     {isPlay?'needleRotate':''}}" src=""></image>

旋转动画:

/* 磁盘的动画 : infinite 无限循环*/
.discAnimation{
    
    
    animation: disc 4s linear infinite;
    animation-delay: 1s; /* 动画延迟1s 当遥感到位旋转*/
}
/* @keyframes :设置帧动画
1) from to:
    使用与简单的动画,只有起始帧和结束帧
2) 百分比
    多用于复杂的动画,动画不止两帧
*/
@keyframes disc {
    
    
    from{
    
    
        transform:rotate(0deg);
    }
    to{
    
    
        transform:rotate(360deg);
    }
}
<view class="discContainer {
     
     {isPlay && 'discAnimation'}}">

1. 路由页面 跳转 传参

知识点1:

点击事件传参数 : data-key=valuse

<view data-song="{
     
     {item}}" bindtap="toSongDetail">

响应函数接参数:let x = event.currentTarget.dataset.key;

let song = event.currentTarget.dataset.song;

知识点2:

路由页面跳转 传参数:url:"***?song="+song
JSON.stringify(song)先要将对象转换成字符串

// 路由跳转传参:query 参数
wx.navigateTo({
    
    
      url:"***?song="+ JSON.stringify(song) // 
})

路由跳转页面接收参数:

onLoad: function (options) {
    
    
  // 1. options:用于接收路由跳转的query参数
  // 2. 原生小程序中路由传参,对参数的长度有限制,如果参数过长会自动截取掉
  console.log(options)
},

由于通过上面的方法item一项的数据很大,所有在传参的时候会自动截取掉,所有实践中传 歌曲的id过去。

2. 获取详情歌曲数据

在这里插入图片描述

页面传参:

  // 点击歌曲 跳转不同的详情页
  toSongDetail(event){
    
    
    // 接收参数
    let song = event.currentTarget.dataset.song;
    // 路由跳转传参:query 参数
    wx.navigateTo({
    
    
      url:"/pages/songDetail/songDetail?musicId="+ song.id
    })
  },

接收参数:

onLoad: function (options) {
    
    
  // 1. options:用于接收路由跳转的query参数
  // 2. 原生小程序中路由传参,对参数的长度有限制,如果参数过长会自动截取掉
  let musicId = options.musicId
},

获取歌曲详情:

// 获取音乐的详情的功能函数
async getMusicInfo(musicId) {
    
    
  let songData = await request("/song/detail",{
    
    ids:musicId})
  this.setData({
    
    
    song:songData.songs[0]
  })
},

3. 动态设置页面标题

wx.setNavigationBarTitle(Object object)

在这里插入图片描述

// 动态修改窗口的标题
wx.setNavigationBarTitle({
    
    
  title:this.data.song.name
})

4. 音乐播放和暂停

背景音频 :BackgroundAudioManager

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

4.1 播放 和 暂停

后台播放需要设置:
在这里插入图片描述
在这里插入图片描述

在这里插入图片描述

代码:

  // 控制音乐播放/暂停的功能函数
  async musicControl(isPlay, musicId) {
    
    
    let backgroundAudioManager = wx.getBackgroundAudioManager();
    if (isPlay == true) {
    
     // 音乐播放
      console.log("播放!");
      // 获取播放链接
      let musicLickData = await request("/song/url", {
    
    id: musicId});
      let musicLick = musicLickData.data[0].url;
      backgroundAudioManager.src = musicLick; // 添加音乐播放链接
      backgroundAudioManager.title = this.data.song.name;
    } else {
    
     // 音乐暂停
      console.log("暂停!");
      backgroundAudioManager.pause(); // 音乐暂停
    }
  },

5. 决解系统任务栏控制音乐播放状态显示不一致问题

BackgroundAudioManager

当用户点击系统的控制栏时,小程序没有检测到

在这里插入图片描述
在这里插入图片描述

/**
   * 生命周期函数--监听页面加载
   */
  onLoad: function (options) {
    
    
    /* 问题: 如果用户操作系统的控制音乐或者暂停的按钮,页面不知道,导致页面显示是否播放的状态和真实的音乐播放状态不一致
    *  解决方案:
    *     1. 通过控制音频的实例 backgroundAudioManager 去监听音乐播放/暂停
    *
    * */
    // 创建音乐控制播放实例
    this.backgroundAudioManager = wx.getBackgroundAudioManager();
    // 监听音乐播放/暂停/停止
    this.backgroundAudioManager.onPlay(()=>{
    
    
      this.changePlayState(true);
    });
    this.backgroundAudioManager.onPause(()=>{
    
    
      this.changePlayState(false);
    });
    this.backgroundAudioManager.onStop(()=>{
    
    
      this.changePlayState(false);
    });
  },

  // 修改播放状态的功能函数
  changePlayState(isPlay){
    
    
    this.setData({
    
    
      isPlay:isPlay
    })
  },

6. getApp决解页面销毁音乐播放状态问题

AppObject getApp(Object object)

在这里插入图片描述
在这里插入图片描述

在这里插入图片描述

全局保存音乐播放数据:
app.js

App({
    
    

  globalData:{
    
    
    isMusicPlay:false, // 全局标识是否有音乐播放
    musicId:"", // 音乐id
  },
})

songDetail.js

// 获取全局实例
const appInstance = getApp();
  /**
   * 生命周期函数--监听页面加载
   */
  onLoad: function (options) {
    
    
    let musicId = options.musicId;
    this.setData({
    
    
      musicId:musicId
    });
    // 获取音乐详情
    this.getMusicInfo(musicId);

    /* 问题: 如果用户操作系统的控制音乐或者暂停的按钮,页面不知道,导致页面显示是否播放的状态和真实的音乐播放状态不一致
    *  解决方案:
    *     1. 通过控制音频的实例 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);
    });
  },

  // 修改播放状态的功能函数
  changePlayState(isPlay){
    
    
    this.setData({
    
    
      isPlay:isPlay
    });
    // 修改全局音乐播放的状态
    appInstance.globalData.isMusicPlay=isPlay;
  },

7. 通过页面通信,npm包的使用

7.1 小程序使用 npm 包

1. 初始化 package.json

npm init或者 npm init -y
在这里插入图片描述
一直回车就好了

在这里插入图片描述
生成的这个package.json可以看作这个项目的说明书

2. 勾选允许使用 npm
在这里插入图片描述

3. 下载 npm包

npm install packageName

4. 构建 npm

  1. 开发者工具 --> 工具 --> 构建 npm
  2. 会自动将 node_modules 中的包,打包到 miniprogram_npm 中在这里插入图片描述

7.2 pubsub消息订阅发布,自定义事件说明

pubsun包可以帮助完成页面与页面之间的通信!

https://github.com/mroderick/PubSubJS
Install via npm (npm install pubsub-js)

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

7.3 页面通信实现

recommendSong 与 songDetail界面通信!
在这里插入图片描述

recommendSong.js

onLoad: function (options) {
    
    
......其他代码

    // ** 订阅(绑定)来自songDetail 页面发布的消息
    PubSub.subscribe("switchType",(msg,data)=>{
    
    
      let {
    
    recommendList,index} = this.data;
      if(data === "pre"){
    
     // 上一首
        index-=1;
        if(index==-1) index=recommendList.length-1;
      }else{
    
     // 下一首
        index=(index+1)%recommendList.length;
      }
      this.setData({
    
    
        index:index
      })
      let musicId = recommendList[index].id; // 将要更新的id
      // 将musicId 回传给songDetail页面
      PubSub.publish("musicId",musicId);
    });
 }

songDetail.js

  // 点击切换歌曲回调函数
  handleSwitch(event){
    
    
    // 获取切换的类型
    let type = event.currentTarget.id;
    // 发布消息数据给recommendSong页面
    PubSub.publish("switchType",type);

    // 接收musicId
    PubSub.subscribe("musicId",(msg,data)=>{
    
    
      console.log(msg,data);
      // 取消订阅
      PubSub.unsubscribe("musicId"); 
    });
  },

8. 歌曲进度条

知识点1:

http://momentjs.cn/ 专门处理时间的库

npm install moment
在这里插入图片描述
引入包需要 构建一下

 // songData.data.dt 就是总时长( 毫秒)
 let durationTime = moment(songData.songs[0].dt).format("mm:ss");

知识点2:

在这里插入图片描述
在这里插入图片描述

 <!--  进度条控制区域  -->
 <view class="programControl">
     <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>
/* 进度条控制区域 */
.programControl{
    
    
    position: absolute;
    width: 640rpx;
    height: 80rpx;
    bottom: 200rpx;
    line-height: 80rpx;
    display: flex;
}

.barControl{
    
    
    position: relative;
    width: 430rpx;
    height: 4rpx;
    margin: auto;
    background: rgba(0,0,0,0.4);
}
.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: #ffffff;
}
data: {
    
    
  currentTime:"00:00", //实时的时间
  durationTime:"00:00", // 歌曲总时长
  currentWidth:0, // 实时播放长度
},
  
onLoad: function (options) {
    
    
    // 监听背景音频播放进度更新事件,只有小程序在前台时会回调。
    this.backgroundAudioManager.onTimeUpdate(()=>{
    
    
      let currentTime = moment(this.backgroundAudioManager.currentTime*1000).format("mm:ss");
      let currentWidth = (this.backgroundAudioManager.currentTime/this.backgroundAudioManager.duration) * 430;
      this.setData({
    
    
        currentTime:currentTime,
        currentWidth:currentWidth
      });
    });
},

9. 一首播放完成自动切换下一首

// 监听音乐播放自然结束
this.backgroundAudioManager.onEnded(()=>{
    
    
  // 自动切换下一首,自动播放
  PubSub.publish("switchType","next");
  // 进度条恢复 0
  this.setData({
    
    
    currentWidth:0,
    currentTime:"00:00", //实时的时间
  })
});

在这里插入图片描述

今天拼多多赚了100 费了九牛二虎之力。。。直接卸载软件。。。

猜你喜欢

转载自blog.csdn.net/qq_45021180/article/details/113106496