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

一、转发分享功能

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

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

Button
在这里插入图片描述
微信小程序【网易云音乐实战】(第五篇 转发分享、每日推荐、音乐播放、页面通信npm包、进度条、全局数据)_第2张图片

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

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

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


二、每日推荐歌曲

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

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

<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的动态控制:

方式一:&&
<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. 获取详情歌曲数据

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

页面传参:

  // 点击歌曲 跳转不同的详情页
  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)

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

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

4. 音乐播放和暂停

背景音频 :BackgroundAudioManager

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

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

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

4.1 播放 和 暂停

后台播放需要设置:
在这里插入图片描述
微信小程序【网易云音乐实战】(第五篇 转发分享、每日推荐、音乐播放、页面通信npm包、进度条、全局数据)_第11张图片

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

代码:

  // 控制音乐播放/暂停的功能函数
  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

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

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

/**
   * 生命周期函数--监听页面加载
   */
  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)

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

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

全局保存音乐播放数据:
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
微信小程序【网易云音乐实战】(第五篇 转发分享、每日推荐、音乐播放、页面通信npm包、进度条、全局数据)_第18张图片
一直回车就好了

微信小程序【网易云音乐实战】(第五篇 转发分享、每日推荐、音乐播放、页面通信npm包、进度条、全局数据)_第19张图片
生成的这个package.json可以看作这个项目的说明书

2. 勾选允许使用 npm
微信小程序【网易云音乐实战】(第五篇 转发分享、每日推荐、音乐播放、页面通信npm包、进度条、全局数据)_第20张图片

3. 下载 npm包

npm install packageName

4. 构建 npm

  1. 开发者工具 --> 工具 --> 构建 npm
  2. 会自动将 node_modules 中的包,打包到 miniprogram_npm 中微信小程序【网易云音乐实战】(第五篇 转发分享、每日推荐、音乐播放、页面通信npm包、进度条、全局数据)_第21张图片

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

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

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

在这里插入图片描述

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

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

7.3 页面通信实现

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

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
微信小程序【网易云音乐实战】(第五篇 转发分享、每日推荐、音乐播放、页面通信npm包、进度条、全局数据)_第25张图片
引入包需要 构建一下

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

知识点2:

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

 
 <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 费了九牛二虎之力。。。直接卸载软件。。。

你可能感兴趣的:(微信小程序开发,小程序)