zoukankan      html  css  js  c++  java
  • 小程序网易云(四)

    一,视频模块,上一个视频在播放,下一个视频点击播放,上一个视频需要暂停播放

    1,1,此时有个bug,点击下一个视频,上一个视频还在继续播放

    1.2,wx.createVideoContext(string id, Object this),创建 video 上下文 VideoContext 对象,video 组件的 id,

    VideoContext.play()
    播放视频

    VideoContext.pause()
    暂停视频

    bindplay, 当开始/继续播放时触发play事件

    poster,视频封面的图片网络资源地址或云文件ID(2.3.0)。若 controls 属性值为 false 则设置 poster 无效

    button的open-type属性,授权行为,share合法值,触发用户转发

    onShareAppMessage(Object object),只有定义了此事件处理函数,右上角菜单才会显示“转发”按钮

    监听用户点击页面内转发按钮(button 组件 open-type="share")或右上角菜单“转发”按钮的行为,并自定义转发内容。

    1.3,上一个视频在播放,点击下一个视频,上一个视频暂停

    <video class="common" 
            id="{{'video'+item.data.vid}}" 
            src="{{item.data.urlInfo.url}}"
            bindplay="handlePlay"
        ></video>

    js代码,

     //用于监视视频的播放状态
      handlePlay(event){
        //记录当前正在播放的视频的id->vid
        let vid = event.target.id;
        // 要过滤当前视频vid,不然当前点击当前视频一直是暂停的
        this.videoContext &&vid!==this.data.vid&& this.videoContext.pause();
        this.setData({ vid });
        //停止上一个视频的播放
        //1.拿到上一个视频的videoContext上下文对象
        this.videoContext = wx.createVideoContext(vid);
    
        // 延迟两秒钟后暂停该视频
        // let videoContext = wx.createVideoContext(vid);
        // setTimeout(videoContext.pause,10000);
        // console.log(event)
        // console.log('playing')
      },

    1,4 视频模块,性能优化

    同一页面存在多个video时,video无法正常播放一直在加载转圈

    不建议同个页面使用多个video组件,建议不超过3个video,如果要实现video列表功能,请进行优化(image列表,选中时将image替换成video

    视频模块(性能优化)
      问题:官方建议通个页面不超过3个video组件,但是我们项目中视频列表明显不符合
      解决:可以用image列表替换成视频列表,当用户点击某个的image组件的时候在将他切换成video组件,进行视频播放
      1)通过给video组件添加标签属性poster,实现视频默认显示某个画面
      2)新增一个image组件,显示与视频相同的图片,并设置相同样式
      3)页面刚显示时,默认显示image组件,video组件隐藏(image组件和video组件显示切换用状态控制)
      4)给image组件绑定点击事件,当用户点击image组件,隐藏当前image组件,显示对应的video组件
      5)效果完成,提升用户体验!!!
        问题:目前点击image组件会切换显示video组件,但是还需要再点击video组件,才能进行播放
        解决:创建videoContext,调用play方法进行,实现video组件自动播放
      6)优化代码!!!
        需求:将handlePlay与image的handleTrigger合并为一个函数
      7)提升用户体验!!!
        问题:当前video组件内显示的画面左右有黑色"边框",并未填充完整,与image组件切换时有些突兀
        解决方案1(效果较差):将video组件上的标签属性object-fit设置为fill        缺点:会使部分竖屏视频效果会被拉伸是去原有比例,效果较差
        解决方案2(效果较好):将video标签宽度和高度的比例设置的跟图片原有高度相同,通过video标签宽度计算高度

    当图片的id和video的id相同时,显示video组件。

     <view class="videoItem" wx:for="{{videoList}}" wx:key="id">
          <video class="common" 
            id="{{'video'+item.data.vid}}" 
            src="{{item.data.urlInfo.url}}"
            bindplay="handleTrigger"
            poster="{{item.data.coverUrl}}"
            wx:if="{{'video'+item.data.vid===vid}}"
        ></video>
          
          <image 
          wx:else
          class="common" 
          bindtap="handleTrigger" 
          id="{{'video'+item.data.vid}}" 
          src="{{item.data.coverUrl}}"></image>

    js, 点击图片切换到video组件时,通过videoContext.play();自动播放

      data: {
        videoGroup:[],
        id:null,
        trigger:false,
        videoList:[],
        vid: ""
      },
      //用于切换image组件与video组件的函数
      handleTrigger(event){
        // console.log('handleTrigger');
        let vid = event.target.id;
        // console.log(vid)
        this.setData({ vid });
        // 生成当前图片对应视频的videoContext
        let videoContext = wx.createVideoContext(vid);
        //通过videoContext的play方法,控制视频播放
        videoContext.play();
      },

    1.5,视频模块分享功能

    视频模块(分享功能)
      1)需要注意,由于项目还在开发期间,分享小程序给好友,好友必须要有体验权限才可以点开(可以在小程序开发中心设置)
      2)通过给button组件添加标签属性open-type,设置为share,点击之后就会自动触发页面的事件函数onShareAppMessage
      3)在onShareAppMessage中,return对象,自定义标题等数据
      4)通过event.target的值区分当前的分享功能的来源
        到底是点击右上角的分享触发的,还是点击button触发的
          1.如果是右上角分享的就显示默认的小程序截图
          2.如果是点击button触发的,就分享按钮对应的图片以及标题

    button的open-type属性,授权行为,share合法值,触发用户转发
    
    onShareAppMessage(Object object),只有定义了此事件处理函数,右上角菜单才会显示“转发”按钮
    监听用户点击页面内转发按钮(button 组件 open-type="share")或右上角菜单“转发”按钮的行为,并自定义转发内容。
    
    from参数,
    转发事件来源。
    button:页面内转发按钮;
    menu:右上角转发菜单
    此事件处理函数需要 return 一个 Object,用于自定义转发内容

     <button open-type="share" data-title="{{item.data.title}}" data-imageurl="{{item.data.coverUrl}}" class="item btn">
                <text class="iconfont icon-gengduo"></text>
              </button>

    js代码,获取自定义的属性时,需要小写,比如imageurl

     
    /**
       * 用户点击右上角分享
       */
      onShareAppMessage: function (shareObj) {
      
        // console.log(shareObj)
        // 1.通过传入的实参内部的from属性进行判断,区分分享的来源
        // button代表button组件,menu代表右上角分享
        if(shareObj.from==="button"){
          let { title,imageurl } = shareObj.target.dataset;
          console.log('我是通过button分享的')
          //通过return一个配置对象,配置分享的内容
          return {
            title,
            path:"/pages/video/video",
            imageUrl:imageurl
          }
        } else if (shareObj.from === "menu") {
          console.log('我是通过右上角转发分享的')
        }
      }

    二,每日推荐模块,数据动态渲染

        接口地址 : /recommend/songs
        调用例子 : /recommend/songs
        注意事项: 
        需要登录,携带cookie
        数据量大,可自行整合
        返回数据: 

    2.1,日期获取

     <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>
    this.setData({
          day: new Date().getDate(),
          month: new Date().getMonth() + 1
        })

    2.2,发送请求,获取数据

     let result = await request('/recommend/songs');
        // console.log(result)
        this.setData({
          recommendList: result.recommend
        })
      data: {
        month:"",
        day:"",
        recommendList:[]
      },

    2.3,页面数据渲染

     <!-- 音乐列表 -->
        <scroll-view class="scrollView" scroll-y>
          <view class="recommendItem" 
            bindtap="toSong"
            data-id="{{item.id}}"
            wx:for="{{recommendList}}" 
            wx:key="id">
            <!-- 
                  data-index="{{index}}" 可行
                  data-item="{{item}}"  不可行,数据体积太大,转换成json字符串传不过去
            -->
            <image src="{{item.album.picUrl}}"></image>
            <view class="musicContent">
              <text class="musicName">{{item.name}}</text>
              <text class="author">{{item.artists[0].name}}</text>
            </view>
            <view class="radio">
              <text class="iconfont icon-gengduo"></text>
            </view>
          </view>
        </scroll-view>

    2.4,页面加载音乐列表页,如果没有登录,也就没有携带cookie,需要弹框,指引去登录

    wx.showModal(Object object),显示模态对话框(API--界面-交互)

    wx.navigateBack(Object object),关闭当前页面,返回上一页面或多级页面。可通过 getCurrentPages 获取当前的页面栈,决定需要返回几层。

     只有登录过后,歌曲信息才会请求成功

     onLoad: async function (options) {
        // console.log(new Date().getDate())
        // console.log(new Date().getMonth()+1)
        //获取当前最新时间,并更新到状态中
        this.setData({
          day: new Date().getDate(),
          month: new Date().getMonth() + 1
        })
        // 没有登录过
        if(!wx.getStorageSync('cookies')){
          wx.showModal({
            title:"请先登录",
            content:"该功能需要登录帐号",
            cancelText:"回到首页",
            confirmText:"去登陆",
            success(res){
              // 去登录按钮
              if(res.confirm){
                wx.redirectTo({
                  url: '/pages/login/login',
                })
              }else{
                wx.navigateBack();
              }
              // console.log(res)
            }
          })
        }
        let result = await request('/recommend/songs');
        // console.log(result)
        this.setData({
          recommendList: result.recommend
        })
      },

    在index页,点击每日推荐按钮,跳转到每日推荐页recommendSong

    <view class="headerItem" bindtap="toRecommendSong">
          <text class="iconfont icon-meirituijian-"></text>
          <text>每日推荐</text>
        </view>
      toRecommendSong(){
        wx.navigateTo({
          url: '/pages/recommendSong/recommendSong'
        })
      },

    三,播放歌曲静态页面搭建song以及动态交互

    获取音乐详情
        必选参数 : ids: 音乐 id, 如 ids=347230
        接口地址 : /song/detail
        调用例子 : /song/detail?ids=347230
        返回数据格式:

    在每日推荐歌曲中,点击一条歌曲,跳转到歌曲播放页面,此时需要传递id到歌曲详情页

    在推荐歌曲页

     <scroll-view class="scrollView" scroll-y>
          <view class="recommendItem" 
            bindtap="toSong"
            data-id="{{item.id}}"
            wx:for="{{recommendList}}" 
            wx:key="id">
            <!-- 
                  data-index="{{index}}" 可行
                  data-item="{{item}}"  不可行,数据体积太大,转换成json字符串传不过去
            -->
            <image src="{{item.album.picUrl}}"></image>
            <view class="musicContent">
              <text class="musicName">{{item.name}}</text>
              <text class="author">{{item.artists[0].name}}</text>
            </view>
            <view class="radio">
              <text class="iconfont icon-gengduo"></text>
            </view>
          </view>
        </scroll-view>

    js代码,query路由传参,有大小限制

    每日推荐模块(重点:路由传参)
      1)给每个recommendItem绑定tap事件,当点击之后跳转页面至播放歌曲页面
      2)当页面进行跳转时候,要显示对应歌曲内容的播放歌曲页面,出现问题!!!
        问题1:如何将即将播放歌曲的数据对象,从每日推荐页面传递至播放歌曲页面
        解决:以query格式进行路由传参,播放歌曲页面通过onLoad的形参options接收
        
        问题2:经过问题1,我们成功将数据对象传给了播放歌曲页面,但是由于url长度限制,数据无法完整传到播放歌曲页面
        解决:思路出错,更换思路
      3)由于能传的数据量有限,所以我们将传的数据从歌曲对象换成歌曲的id
      4)在播放歌曲页面的onLoad函数中获取到歌曲的id,并发送请求到服务器,请求数据,并保存到状态中
      5)使用状态数据实现页面动态渲染,通过wx.setNavigationBarTitle设置播放歌曲页面标题
    // 用于跳转详情页面
      toSong(event){
        let {id} = event.currentTarget.dataset;
        // console.log('id',id);
        wx.navigateTo({
    url:
    '/pages/song/song?songId=' + id }) },

    在歌曲播放详情页,发送请求,获取歌曲图片,作者数据

    wx.setNavigationBarTitle(Object object),动态设置当前页面的标题

    onLoad: async function (options) {
         // 通过options可以拿到query参数
        // 1.跳转页面时,通过query传参,对url进行拼接
        // 2.在onLoad中的形参options中,可以或得到所有的query键值对
        // console.log(options.songId);
        let {songId} = options;
        this.setData({
          songId
        })
    
        //1.请求数据
        let result = await request('/song/detail', { ids:songId });
        // console.log(result)
    
        //2.保存至data中
        this.setData({
          songObj:result.songs[0]
        })
        // 动态设置顶部标题
        wx.setNavigationBarTitle({
          title: this.data.songObj.name
        })
    
        //3.动态渲染
    
      
      },

    数据渲染

    <view class="songContainer {{isplaying?'isplaying':''}}">
      <text class="name">{{songObj.ar[0].name}}</text>
      <view class="keng"></view>
      <image class="needle" src="/static/images/song/needle.png"></image>
      <view class="discContainer">
        <image class="disc" src="/static/images/song/disc.png"></image>
        <image class="discImg" src="{{songObj.al.picUrl}}"></image>
      </view>

    发送请求,获取歌曲音频连接数据

    获取歌曲播放地址
        必选参数 : id : 音乐 id
        接口地址 : /song/url
        调用例子 : /song/url?id=33894312 

    背景音频,BackgroundAudioManager,BackgroundAudioManager 实例,可通过 wx.getBackgroundAudioManager 获取
    获取全局唯一的背景音频管理器。 小程序切入后台,如果音频处于播放状态,可以继续播放。但是后台状态不能通过调用API操纵音频的播放状态
    string src
    音频的数据源(2.2.3 开始支持云文件ID)。默认为空字符串,当设置了新的 src 时,会自动开始播放,目前支持的格式有 m4a, aac, mp3, wav

    string title
    音频标题,用于原生音频播放器音频标题(必填)。原生音频播放器中的分享功能,分享出去的卡片标题,也将使用该值

    boolean paused
    当前是否暂停或停止。(只读

    BackgroundAudioManager.pause()
    暂停音乐

    播放歌曲模块(重点:音乐播放)
      1)由于我们请求回来的歌曲数据中没有音频资源的地址,所以需要再请求另一个专门用户获取音频资源地址的接口
      2)将请求得到的音频资源数据保存至页面状态
      3)优化代码!!!
        问题:用户可能点击每日推荐的某个选项,但是跳转到song页面之后并不播放
        解决:等用户真的有播放歌曲的意愿,再发送请求(点击播放按钮时)
      4)通过wx.getBackgroundAudioManager,获得背景音频的播放器实例
      5)给实例添加属性src和title,当src的值为新值时候,背景音频会自动播放,出现问题!!!
        问题:控制台报错提示,该功能需要配置才能使用
        解决:在app.json中配置requiredBackgroundModes属性
      <!-- 底部播放选项区域 -->
      <view class="musicControl">
        <text class="iconfont icon-iconsMusicyemianbofangmoshiShuffle" ></text>
        <text class="iconfont icon-shangyishou" id="pre"></text>
        <text class="iconfont {{isplaying?'icon-zanting':'icon-bofang'}} big" bindtap="handlePlay"></text>
        <text class="iconfont icon-next" id="next"></text>
        <text class="iconfont icon-iconsMusicyemianbofangmoshiPlayList"></text>
      </view>
    </view>

    js代码

    data: {
        isplaying:false,
        songId:null,
        songObj:{},
        musicUrl:""
      },
    
      async handlePlay() {
        let musicUrlData = await request('/song/url', { id: this.data.songId });
        this.setData({
          isplaying: !this.data.isplaying,
          musicUrl: musicUrlData.data[0].url
        })
        // 获取音频实例
        let backgroundAudioManager = wx.getBackgroundAudioManager();
        // console.log('paused',backgroundAudioManager.paused);
        // paused是只读属性,false是正在播放,true代表已停止或者暂停
        // paused值在首次读取时,一定是undefined
        //pause是方法,调用它可以暂停音频
        if (backgroundAudioManager.paused || typeof backgroundAudioManager.paused === "undefined") {
          // 音频连接
          backgroundAudioManager.src = this.data.musicUrl;
          // 音频标题,必传
          backgroundAudioManager.title = this.data.songObj.name;
        } else {
          // 暂停播放
          backgroundAudioManager.pause();
        }
        // this.setData({
        //   isplaying: !this.data.isplaying
        // })
      },

    此时报了个错

     在app.json中配置

    "requiredBackgroundModes": ["audio"],
  • 相关阅读:
    Flume基础(一):概述
    Hive高级(2):优化(2) 表的优化
    ospf命令
    Verizon 和某 BGP 优化器如何在今日大范围重创互联网
    BGP数据中心鉴别方法
    多线BGP鉴定
    mpls ldp neighbor 和loopbak
    ospf默认路由
    ospf
    ubuntu cloud init获取元数据失败
  • 原文地址:https://www.cnblogs.com/fsg6/p/13640493.html
Copyright © 2011-2022 走看看