小程序开发video组件自定义功能

原生的video组件功能已经可以满足用户所有需求,本文介绍一下非正常的用户需求怎么解决。
比如:用户需要限制播放时不能滑动屏幕快进不能拖动进度条快进快退不准倍速播放不准全屏;用户第一次完整看完视频后可以倍速,快进,暂停和全屏。
解决的思路:隐藏掉video自带的所有控件功能,包括原生的video功能全部设置为false,然后自己画一个底部控件包含播放按钮还有进度条和全屏按钮,在全屏页面左上角添加返回退出全屏按钮
在这里插入图片描述
上面是效果图;
下面看一下页面中的写法:

<video wx:if="{{videofalse}}" id="myvideo" custom-cache="{{false}}" bindpause="bindPause" bindplay="bindPlay" bindtimeupdate="bindtimeupdate" bindended="bindended" bindfullscreenchange="bindfullscreenchange" initial-time="{{strtime}}" enable-progress-gesture="{{progress}}" show-progress="{{progress}}" controls="{{progress}}" objectFit="cover" src="{{VideoUrl}}">
   <view class='mast_video' wx:if="{{mast_video}}">
     <button bindtap='seed_change'>倍速</button>
   </view>
   <view class='change_mast' wx:if="{{change_mast}}" bindtap='close_change'>
     <view class='seed_change'>
       <button bindtap="bindButtonRate" data-rate='1.0'>1.0X</button>
       <button bindtap="bindButtonRate" data-rate='1.25'>1.25X</button>
       <button bindtap="bindButtonRate" data-rate='1.5'>1.5X</button>
     </view>
   </view>
   <view class='process-container' wx:if="{{stuflag == true}}">
     <image src='{{playStates ? "/images/main/puse_v.png" : "/images/main/play_v.png"}}' class='video-controls-icon' bindtap='videoOpreation'></image>
     <view class='slider-container'>
     <slider bindchange="sliderChange" bindchanging="sliderChanging" step="0.5" value="{{sliderValue}}" backgroundColor="#A8A8A8" activeColor="#FFFFFF" block-color="#FFFFFF" block-size="14" /><text decode="{{true}}" space="{{true}}">{{canvasTime}}</text>
     </view> 
     <image src='{{playAlls ? "/images/main/play_all.png" : "/images/main/puse_all.png"}}' class='video-controls-icon' bindtap='videoAllscreen'></image>
   </view>
   <view class='video_back'><image src='{{playAlls ? " " : "/images/main/video_back.png"}}' bindtap='video_back'></image></view>
 </video>

有人会说为什么不使用cover-view来实现呢?cover-view是挺方便的,但是它不能实现完全的自我控制,有些属性被微信官方定义死了,还不如使用最基础的view组件和image组件自由
在video组件中将自己需要控制的属性全部使用**{{false}}或者自定义名字来控制**。对自己画出的倍速和控制条的内容使用wx:if来判断可控制还是不可控制

播放按钮和全屏按钮使用三元运算来判断是播放按钮还是暂停按钮,是全屏按钮还是退出全屏按钮。
默认条件为真(true)

 playStates: true, //控制播放 & 暂停按钮的显示
 playAlls: true,

在点击函数中进行判断:

 videoOpreation() { //自定义暂停
    this.data.playStates ? this.videoContext.pause() : this.videoContext.play();
    this.setData({
      playStates: !this.data.playStates
    })
  },
  videoAllscreen(e) { //自定义全屏
    this.data.playAlls ? this.videoContext.requestFullScreen() : this.videoContext.exitFullScreen();
    this.setData({
      playAlls: !this.data.playAlls
    })
  },
  video_back: function (e) {
    this.data.playAlls ? this.videoContext.requestFullScreen() : this.videoContext.exitFullScreen();
    this.setData({
      playAlls: !this.data.playAlls
    })
  },
  sliderChanging(e) { //拖拽过程中,不允许更新进度条
    var new_stuflag = wx.getStorageSync("key_stuflag");
    if (new_stuflag == 1) { //学完允许拖动
      this.setData({
        updateState: false
      })
    } else {

    }

  },
  sliderChange(e) {
    var new_stuflag = wx.getStorageSync("key_stuflag");
    if (new_stuflag == 1) { //学完允许拖动
      if (this.data.duration && obj == 200) { //完成拖动后,计算对应时间并跳转到指定位置
        this.videoContext.seek(e.detail.value / 100 * this.data.duration);
        this.setData({
          sliderValue: e.detail.value,
          updateState: true //完成拖动后允许更新滚动条
        })
      } else { }
    } else { }


  },

通过自定义函数来控制自定义组件的内容。然后在第一遍播放完成度额时候给后台提交播放信息和时长,根据返回结果来开放video组件的相应属性功能。

bindended: function (res) { //第一遍结束
    var that = this,
      obj_time = wx.getStorageSync("v_time"), //本次学习时长
      userNid = wx.getStorageSync("unionid"),
      vid = wx.getStorageSync("bo_vid"),
      bid = wx.getStorageSync("ke_id");
    wx.request({
      url: app.globalData.Url + "/api/users/event/addstudent/", //进度提交
      data: {
        unionid: userNid,
        vid: vid + 1,
        bid: bid,
        stime: obj_time
      },
      method: "POST",
      header: {
        'content-type': 'application/x-www-form-urlencoded' // 默认值
      },
      success: function (res) {
        wx.setStorageSync("key_stuflag", res.data.stuflag)
        if (res.data.stuflag == 0) { //根据学习进度状态改变是否可快进
          that.setData({
            progress: false,
            mast_video: false,
            stuflag: true
          })
        } else {
          that.setData({
            progress: true,
            stuflag: false,
            mast_video: true,
          })
        }
      }
    })

  },
  bindButtonRate(e) { //倍速
    var that = this;
    let rate = e.currentTarget.dataset.rate
    this.videoContext.playbackRate(Number(rate))
    setTimeout(function () {
      that.setData({
        change_mast: false,
        mast_video: true,
      })
    }, 400)
  },
  seed_change: function (s) { //按钮展开倍速
    this.setData({
      mast_video: false,
      change_mast: true,
    })
  },
  close_change: function () { //空白处关闭倍速
    this.setData({
      mast_video: true,
      change_mast: false,
    })
  },

这样自定义video功能就准备齐全了。
根据评论区需求,加上本页面CSS样式:


.weui-cells {
  margin-top: 80rpx;
  text-align: left;
}

.weui-label {
  width: 5em;
}

.coursedes-item {
  border-bottom: 1rpx solid #e5e5e5;
  padding: 40rpx 10rpx;
  font-size: 26rpx;
  color: #141414;
  line-height: 39rpx;
  text-indent: 52rpx;
  text-align: justify;
}

.conact {
  width: 100%;
  height: 105rpx;
  padding: 12.5rpx 0 12.5rpx 10rpx;
  background: #ccc;
  position: fixed;
  bottom: 0px;
  left: 0;
  right: 0;
  min-height: 105rpx;
}

.search-left {
  flex: 6;
  background: #fff;
  text-align: left;
}

.search-left input {
  display: inline-block;
  height: 85rpx;
  font-size: 26rpx;
  width: 100%;
}

.search-placeholder {
  color: #333;
  line-height: 85rpx;
  font-size: 26rpx;
  margin-left: 20px;
}

.sCode image {
  width: 44rpx;
  height: 44rpx;
  padding: 10rpx 10rpx;
}

.conact .search-left image {
  width: 40rpx;
  height: 40rpx;
  padding: 10rpx;
  float: right;
}

.conact .search-right {
  flex: 1;
}

.conact .search-right image {
  width: 64rpx;
  height: 64rpx;
}

.kefuBtn {
  background-color: rgba(255, 255, 255, 0);
  border: 0px;
  right: 0;
  display: flex;
  justify-content: center;
  align-items: center;
}

.kefuBtn::after {
  border: 0px;
}

.fenxBtn {
  background-color: rgba(255, 255, 255, 0);
  border: 0px;
  left: 0;
  flex: 1;
}

.fenxBtn::after {
  border: 0px;
}

.fenxBtn image {
  width: 44rpx;
  height: 44rpx;
  padding: 14rpx 5rpx;
}

.pof {
  position: fixed;
}

video {
  width: 100%;
  height: 430rpx;
}

.video_top {
  width: 100%;
  height: 430rpx;
}

.page-body-button {
  margin-bottom: 30rpx;
  font-size: 30rpx;
  line-height: 90rpx;
}

.top_img {
  width: 100%;
  height: 430rpx;
  display: flex;
  align-items: center;
  justify-content: center;
  position: absolute;
  left: 0;
  top: 0;
  z-index:19;
  background:#333;
}

.top_img .cover_img {
  width: 90rpx;
  height: 90rpx;
  z-index:5;
}

video .content {
  display: flex;
  justify-content: center;
  align-items: center;
  position: absolute;
  left: 0;
  bottom: 0;
  z-index: 1;
  width: 100%;
  height: 75rpx;
  font-size: 32rpx;
  color: #fff;
}

video .content cover-image {
  width: 44rpx;
  height: 44rpx;
}

.page-cont {
  height: 100%;
}

.belly-scroll {
  width: 100%;
  height: auto;
  background-color: #f5f5f5;
  overflow: hidden;
}

.hook {
  width: 100%;
  height: auto;
}

.header-info {
  padding: 0 30rpx;
  background-color: #fff;
  margin-bottom: 10rpx;
}

.header-info .title {
  font-size: 36rpx;
  color: #333;
  line-height: 1.2;
  padding-top: 30rpx;
  margin-bottom: 10rpx;
}

.header-info .desc {
  font-size: 28rpx;
  color: #555;
}

.header-info .video-total {
  margin-top: 30rpx;
  padding-bottom: 20rpx;
}

.header-info .user-cont {
  font-size: 24rpx;
  color: #808080;
}

.header-info .user-cont label {
  font-size: 28rpx;
  color: #1a1a1a;
}

.header-info .user-tool {
  height: 46rpx;
}

.header-info .play-audio {
  color: #c21327;
  font-size: 22rpx;
  padding: 0 10rpx;
  height: 38rpx;
  border: 1rpx solid #c21327;
  margin-right: 55rpx;
}

.header-info .play-audio image {
  width: 40rpx;
  height: 40rpx;
  margin-right: 10rpx;
}

.header-info .recomment {
  width: 42rpx;
  height: 42rpx;
  margin-top: 2rpx;
  margin-right: 40rpx;
}

.header-info .recomment image {
  width: 40rpx;
  height: 40rpx;
}

.header-info .share {
  width: 42rpx;
  height: 42rpx;
  margin-top: 2rpx;
  margin-right: 5rpx;
}

.header-info .share image {
  width: 40rpx;
  height: 40rpx;
}

.header-info .share-tips {
  white-space: nowrap;
  padding: 0 15rpx;
  height: 38rpx;
  line-height: 38rpx;
  position: fixed;
  right: 6%;
  margin-top: 8px;
  font-size: 22rpx;
  color: #c21327;
  border-radius: 19rpx;
  border: 1px solid #c21327;
  background-color: #fbebed;
}

.header-info .share-tips:before {
  content: '';
  position: absolute;
  right: -1px;
  top: -7rpx;
  width: 16rpx;
  height: 30rpx;
  background-color: #fbebed;
  transform: skewY(-36deg);
  border-top: 1.5px solid #c21327;
  border-right: 1px solid #c21327;
}

.header-info .share-tips:after {
  content: '';
  position: absolute;
  top: 0;
  right: 0;
  background-color: #fbebed;
  width: 20rpx;
  height: 5rpx;
}

.column-inner {
  background-color: #fff;
}

.column-box {
  width: 100%;
  height: 88rpx;
  background-color: #fff;
}

.column-box .column-content {
  width: 100%;
  height: 88rpx;
  border-bottom: 1px solid #eee;
  background-color: #fff;
}

.column-box .column-pof {
  position: absolute;
  top: 430rpx;
  left: 0;
  z-index: 100;
}

.column-box .column-item {
  flex: 1;
  text-align: center;
  padding-top: 15rpx;
  line-height: 68rpx;
  font-size: 28rpx;
  color: #666;
}

.column-box .column-item.active {
  color: #c21327;
  position: relative;
}

.column-box .column-item.active:before {
  content: '';
  width: 50rpx;
  height: 4rpx;
  background-color: #c21327;
  position: absolute;
  bottom: 0;
  left: 50%;
  margin-left: -25rpx;
}

.footer {
  width: 100%;
  height: 102rpx;
  border-bottom: 1rpx solid #e6e6e6;
  left: 0;
  background-color: #fff;
}

.go-home {
  width: 100rpx;
  flex-wrap: wrap;
  font-size: 0;
  line-height: 1.2;
}

.go-home image {
  width: 38rpx;
  height: 38rpx;
  position: relative;
  top: 8rpx;
}

.go-home label {
  width: 100%;
  text-align: center;
  font-size: 24rpx;
  color: #999;
}

.pay-box {
  flex: 1;
  width: 650rpx;
  padding-right: 26rpx;
  padding-left: 26rpx;
}

.pay-box button {
  width: 300rpx;
  height: 80rpx;
  border: 1px solid #c21327;
  text-align: center;
  line-height: 78rpx;
  border-radius: 10rpx;
  font-size: 28rpx;
  color: #4c4c4c;
}

.pay-box button label {
  color: #c21327;
}

.pay-box .vip-btn {
  color: #fff;
  background: #c21327;
}

.evaluate-inner {
  padding: 0 30rpx 30rpx;
  background-color: #fff;
}

.evaluate-item {
  padding: 20rpx 0 20rpx;
  font-size: 26rpx;
  color: #141414;
  line-height: 32rpx;
}

.user-info {
  margin-bottom: 30rpx;
}

.user-box {
  height: 80rpx;
  color: #333;
}

.user-box image {
  width: 80rpx;
  height: 80rpx;
  will-change: transform;
  margin-right: 20rpx;
  border-radius: 100%;
}

.recommend-cont {
  color: #676767;
  font-size: 20rpx;
}

.recommend-cont image {
  width: 23rpx;
  height: 23rpx;
  margin-left: 4rpx;
}

.recommend-cont text {
  margin-left: 12rpx;
  line-height: 1.8;
  padding-top: 5rpx;
}

.eavluate {
  line-height: 1.5;
  border-bottom: 1px solid #eee;
}

.course-list {
  padding: 0 20rpx;
  background-color: #fff;
  color: #1a1a1a;
}

.course-list .title {
  padding-top: 50rpx;
  font-size: 34rpx;
  margin-bottom: 10rpx;
}

.course-item {
  padding: 30rpx 0;
  border-bottom: 1rpx solid #eee;
}

.course-item .course-before {
  font-size: 28rpx;
  width: 520rpx;
}

.course-item .name {
  margin-bottom: 5rpx;
  text-align: left;
  text-overflow: ellipsis;
  white-space: nowrap;
  overflow: hidden;
}

.course-item.active .name {
  color: #c21327;
}

.course-item .info {
  font-size: 24rpx;
  color: #666;
}

.course-item.active .palyer {
  width: 24rpx;
  height: 24rpx;
  margin-left: 8rpx;
}

.experience-icon {
  font-size: 22rpx;
  color: #fff;
  padding: 5rpx 8rpx;
  background-color: #b6985b;
  border-radius: 10rpx;
  vertical-align: initial;
  margin-left: 8rpx;
}

.course-after {
  width: 130rpx;
  height: 55rpx;
  border: 1px solid #c21327;
  color: #c21327;
  border-radius: 26rpx;
  text-align: center;
  background-color: #ffeef0;
}

.course-after image {
  width: 22rpx;
  height: 22rpx;
  margin-right: 6rpx;
}

.course-after.playered {
  background-color: #fff;
}

.evaluate-btn {
  padding: 20rpx 60rpx 50rpx;
}

.evaluate-btn .evaluate-btn-item {
  width: 250rpx;
  height: 80rpx;
  line-height: 78rpx;
  border: 1px solid #ccc;
  border-radius: 40rpx;
  font-size: 28rpx;
  color: #666;
  text-align: center;
  margin: 0 auto;
}

.isPayShow {
  display: block;
}

.isPayHide {
  display: none;
}
.mast_video{
  display:block;
  width:60rpx;
  height:60rpx;
  right:10rpx;
  position:absolute;
  margin-top:165rpx;
  text-align:center;
  border-radius:50%;
  z-index:11;
  background-color: rgba(0,0,0,0.5);
}
.mast_video button{
  font-size:28rpx;
  line-height:60rpx;
  color:#fff;
}
.change_mast{
  width:100%;
  height:430rpx;
  position:relative;
  z-index:13;
  background-color: rgba(0,0,0,0.5);
}
.seed_change{
  width:40%;
  height:60rpx;
  display:flex;
  text-align:center;
  position:absolute;
  top:165rpx;
  left:30%;
  z-index:13;
}
.seed_change button{
  flex:1;
  color:#fff;
}
.process-container{
  width:100%;
  padding:1% 2% 1% 2%;
  height:60rpx;
  max-height:60rpx;
  position:absolute;
  bottom:4px;
  left:0;
  right:0;
  z-index:13;
  display:flex;
  align-items: center;
  background:rgba(59, 57, 57, 0.2);
}
.process-container image{
  display:inline-block;
  flex:1;
  max-width:60rpx;
  max-height:60rpx;
  text-align:center;
}
.slider-container{
  z-index:13;
  height:60rpx;
  margin-bottom:10rpx;
  flex:6;
}
.video_btn{
  flex:1;
}
.video_btn image{
  width:80rpx;
  height:80rpx;
}
.video_time{
  flex:1;
}
.shares{
  width:80rpx;
  height:80rpx;
  position:fixed;
  right:10rpx;
  bottom:160rpx;
  display:flex;
  flex-direction: column;
  align-items: center;
  background-color:#05b5eb;
  color:white;
  border-radius:50%;
  z-index:1;
}
.shares text{
  text-align:center;
  font-size:24rpx;
  color:#fff;
  line-height:36rpx;
}
.video_back{
  display:block;
  width:60rpx;
  height:60rpx;
  left:5rpx;
  top:15rpx;
  position:absolute;
  text-align:center;
  z-index:19;
}
.video_back image{
  width:44rpx;
  height:44rpx;
}

如果有不懂的可以评论区回复,会在不定时进行一一答复。

自定义微信小程序video的进度条,可以使用wx.createVideoContext()方法获取video组件实例,然后通过该实例的属性和方法来实现自定义进度条的效果。 以下是一个简单的示例代码: wxml文件部分: ```xml <video src="{{src}}" id="myVideo"></video> <view class="progress-bar" style="width: {{progress}}%;"></view> ``` js文件部分: ```javascript Page({ data: { src: '视频地址', duration: 0, // 视频总时长 currentTime: 0, // 当前播放时间 progress: 0 // 进度条进度 }, onLoad: function () { // 获取video组件实例 this.videoContext = wx.createVideoContext('myVideo', this); // 监听视频播放时间变化事件 this.videoContext.onTimeUpdate(this.handleTimeUpdate); // 获取视频总时长 this.videoContext.duration((duration) => { this.setData({ duration: duration }); }); }, handleTimeUpdate: function (e) { // 更新当前播放时间和进度条进度 this.setData({ currentTime: e.detail.currentTime, progress: e.detail.currentTime / this.data.duration * 100 }); } }); ``` css文件部分: ```css .progress-bar { height: 6px; background-color: #ccc; } ``` 在上述代码中,我们首先通过wx.createVideoContext()方法获取video组件实例,然后在onLoad()生命周期函数中监听视频播放时间变化事件,并获取视频总时长。在handleTimeUpdate()函数中,我们更新当前播放时间和进度条进度,最后在wxml文件中使用style属性来设置进度条的宽度。 需要注意的是,为了让Video组件支持进度条拖动功能,还需要在wxml文件中添加bindtouchstart、bindtouchmove和bindtouchend事件,并在js文件中添加相应的处理函数。
评论 18
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值