欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

微信小程序video控件的使用

程序员文章站 2022-06-14 13:04:02
...

微信小程序video控件的使用

一、简介

video控件是微信小程序提供的系统组件之一,用于实现播放视频的功能。

二、属性

| 属性名 | 类型 | 默认值 | 说明 | 最低版本 |

|——–|——–|——–|——–|——–|

| src | String| | 要播放视频的资源地址 | |

| initial-time| String | | 指定视频初始播放位置| 1.6.0 |

| duration |Number|| 指定视频时长 | 1.1.0 |

| controls |Boolean |true| 是否显示默认播放控件(播放/暂停按钮、播放进度、时间)| |

| danmu-list |Object Array||弹幕列表 | |

| danmu-btn |Boolean|false | 是否显示弹幕按钮,只在初始化时有效,不能动态变更| |

| enable-danmu |Boolean|false| 是否展示弹幕,只在初始化时有效,不能动态变更 | |

|autoplay|Boolean|false|是否自动播放| |

|loop|Boolean|false|是否循环播放| 1.4.0 |

|muted|Boolean|false|是否静音播放| 1.4.0 |

|page-gesture|Boolean|false|在非全屏模式下,是否开启亮度与音量调节手势|1.6.0 |

|direction|Number||设置全屏时视频的方向,不指定则根据宽高比自动判断。有效值为 0(正常竖向), 90(屏幕逆时针90度), -90(屏幕顺时针90度)|1.7.0|

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

|bindpause|EventHandle||当暂停播放时触发 pause 事件| |

|bindended|EventHandle||当播放到末尾时触发 ended 事件| |

|bindtimeupdate|EventHandle||播放进度变化时触发,event.detail = {currentTime, duration} 。触发频率 250ms 一次| |

|bindfullscreenchange|EventHandle||当视频进入和退出全屏是触发,event.detail = {fullScreen, direction},direction取为 vertical 或 horizontal| |

|objectFit|String|contain|当视频大小与 video 容器大小不一致时,视频的表现形式。contain:包含,fill:填充,cover:覆盖| 1.4.0|

|poster|String||视频封面的图片网络资源地址,如果 controls 属性值为 false 则设置 poster 无效| |

||||||

video 组件 默认宽度300px、高度225px,可通过wxss设置宽高。

三、相关实现api

1、wx.createVideoContext

创建并返回 video 上下文 videoContext 对象。在自定义组件下,第二个参数传入组件实例this,以操作组件内 video 组件

2、videoContext对象

videoContext 通过 videoId 跟一个 video 组件绑定,通过它可以操作一个 video 组件。

videoContext 对象的方法列表:

| 方法 | 参数 | 说明 | 最低版本 |

|——–|——–|——–|——–|

|play | 无| 播放 | |

|pause| 无| 暂停 | |

|seek | position| 跳转到指定位置,单位 s| |

|sendDanmu|danmu|发送弹幕,danmu 包含两个属性 text, color。||

|sendDanmu|danmu|发送弹幕,danmu 包含两个属性 text, color。||

|sendDanmu|danmu|发送弹幕,danmu 包含两个属性 text, color。||

|playbackRate|rate|设置倍速播放,支持的倍率有 0.5/0.8/1.0/1.25/1.5|1.4.0|

|requestFullScreen|无|进入全屏,可传入{direction}参数(1.7.0起支持),详见video组件文档|1.4.0|

|exitFullScreen|无|退出全屏|1.4.0|

四、代码实现

在四川建设厅的代码实现中,我们未涉及弹幕功能的相关使用,所以以下代码不涉及弹幕的代码,如果想自己尝试使用,可以在官网查看其相关代码

实现效果,如下图

微信小程序video控件的使用

实现原理:

在四川建设厅中,我们将视频播放控件进行了组件化的封装,将其放入一个名为courseVideoPlayer的组件中,组件的相关知识,可以查看佳斌写的自定义组件的实现,加以学习。

核心代码:

courseVideoPlayer.wxml


<view>

  <!--poster="{{coverImageUrl}}" -->

  <video id="myVideo" class="myVideo" src="{{playUrl}}" autoplay='false'  controls='true' bindtimeupdate='timeUpdate' bindended='endAction'>

    <!-- <cover-view bindtap='startFirstPlayAction' class='cover-view' wx:if="{{isShowCoverView}}"></cover-view>  -->

    <cover-view bindtap='_startFirstPlayAction' class='cover-view' wx:if="{{isShowCoverView}}">

      <cover-image class='cover-view' src="{{coverImageUrl}}" mode="aspectFill"/>

      <cover-image style='position:absolute; top:50%; left:50%; width:132rpx; height:132rpx; margin:-66rpx 0 0 -66rpx; z-index:10000' src="/image/video-play.png"/>

    </cover-view>

  </video>

</view>


这部分代码主要是视频界面部分,除了使用到video控件之外,我们还用到了cover-view以及cover-image组件,这两个组件的使用,在此,我做一下简单的介绍:

(1)cover-view:覆盖在原生组件之上的文本视图,可覆盖的原生组件包括map、video、canvas、camera,只支持嵌套cover-view、cover-image。

(2)cover-image:覆盖在原生组件之上的图片视图,可覆盖的原生组件同cover-view,支持嵌套在cover-view里。

属性:src String 图标路径,支持临时路径、网络地址(1.6.0起支持)。暂不支持base64格式。

按照功能来说,cover-view和cover-image实质上与普通的基础控件view与image无异,只是这两个控件特殊在,他可以覆盖在map、video、canvas、camera控件中,也正是因为这个特殊性,导致了他们在试用时也存在这一些差异,试用这两个控件的过程中,我们需要考虑以下几个注意点:

* Bug & Tips *

tip: 基础库 1.6.0 起支持css transition动画,transition-property只支持transform (translateX, translateY)与opacity。

tip: 基础库 1.6.0 起支持css opacity。

tip: 只可嵌套在原生组件map、video、canvas、camera内,避免嵌套在其他组件内。

tip: 事件模型遵循冒泡模型,但不会冒泡到原生组件。

tip: 文本建议都套上cover-view标签,避免排版错误。

tip: 只支持基本的定位、布局、文本样式。不支持设置单边的border、background-image、shadow、overflow等。

tip: 建议子节点不要溢出父节点

courseVideoPlayer.js


let studyPlayerManager = require('../../../../utils/studyManager/studyPlayerManager.js')

let currentTime = 0

let videoCtx = null

let app = getApp()

Component({

  /**

   * 组件的属性列表

   */

  properties: {

    playUrl:{

      type:String,

      value:'',

      observer: function (newVal, oldVal) {

        if (newVal.length){

          videoCtx.play()

        }

      }

    },

    totalSecondsTime:{

      type:Number,

      value:10

    },

    playInfo:{

      type: Object,

      value: {},

      observer: function (newVal, oldVal) {

      }

    },

    coverImageUrl:{

      type: String,

      value: '../../../image/course-img.jpg',

      observer: function (newVal, oldVal) {

      }

    },

    isShowCoverView:{

      type:Boolean,

      value:true,

      observer: function (newVal, oldVal) {

      }

    },

    // 初始播放时间

    initialTime : {

      type:Number,

      value:0

    }

  },



  /**

   * 组件的初始数据

   */

  data: {

    lastTime: 0,

    zindex: Math.max,

    currentTime: 0,

    isTest:false

  },

  attached: function () {

    wx.setStorageSync('lastTime', '0');

    wx.setStorageSync('maxTime', '0');

    videoCtx = wx.createVideoContext('myVideo', this)

    // 初始化toast

    new app.WeToast(this)

    studyPlayerManager.initStudyPlayerManager(this)

  },

  moved: function () {

  },

  detached: function () {

    this.studyPlayerManager.deallocStudyPlayerManager()

  },

  /**

   * 组件的方法列表

   */

  methods: {

    play() {

      videoCtx.play()

    },

    pause() {

      videoCtx.pause()

    },

    timeUpdate(e) {

      this.triggerEvent("videoTimeUpdate", e.detail.currentTime)

      var maxTime = parseInt(wx.getStorageSync('maxTime'));

      console.log('maxTime:' + maxTime);

      var lastTime = parseInt(wx.getStorageSync('lastTime'));

      console.log('lastTime:' + lastTime);

      currentTime = e.detail.currentTime;

      console.log('currentTime:' + currentTime)

      if (currentTime != 0 && ((currentTime - lastTime) < 3)) {

        wx.setStorageSync('lastTime', currentTime);

      }

      if (currentTime != 0 && currentTime > maxTime && (((currentTime - lastTime) > 0) && ((currentTime - lastTime) < 3))) {

        wx.setStorageSync('maxTime', currentTime);

        console.log('设置最大时间!')

      }

      if (!this.data.isTest && currentTime > maxTime) {

        if ((currentTime - lastTime) > 3) {

          //跳转到上次的进度

          videoCtx.seek(maxTime);

          wx.setStorageSync('lastTime', maxTime);

          this.wetoast.toast({

            title: '不能进行跳转!请认真学习'

          })

        }

      }

    },

    endAction(e) {

      let maxTime = parseInt(wx.getStorageSync('maxTime'));



      if (!this.data.isTest && ((this.properties.totalSecondsTime - maxTime) > 3)) {

        this.wetoast.toast({

          title: '不能进行跳转!请认真学习'

        })

        videoCtx.seek(maxTime)

        videoCtx.play()

      }else{

        this.triggerEvent("videoPlayEndEvent")

        this._playEndAction()

      }

    },

    fullScreenChangeAction(e) {

      console.log(e)

    },

    changeScreenTap() {

      this.videoCtx.requestFullScreen({ direction: 90 })

    },

    // 跳转到某个点

    seekToPoint(time){

      console.log('跳转到时间:'+time)

      videoCtx.seek(time)

    }

  }

})

代码中,主要实现了对video控件的进度条的拖拽进行了控制,如果在用户将进度条拖拽到还未观看过的视频位置,那么视频将会跳回到用户观看过的最大位置,并提示用户不能进装操作。

由于系统未提供video进度条拖拽的事件监听接口,我们只能“绕个弯”实现该功能。

实现的原理就是通过监听video控件开放的bindtimeupdate播放过程中的进度监听事件,我们通过监听进度条当前的进度与上一次回调的进度进行比较,如果两者之差大于3,便视为用户进行了拖拽操作,具体的代码,查看上述的timeUpdate(e)与endAction(e)事件中的相关代码。

起初,原本想自定义控制器来实现监听视频进度条拖拽的相关功能,但通过实践,我们发现,在video上的cover-view中无法嵌套系统提供的slider组件,同时在video控件上,无法进行自定义拖拽事件的监听(开发工具上可以监听,真机上无法进行监听,具体的原因还需考察),所以目前只能通过该方法实现控制拖拽进度条的操作。

相关标签: video