微信小程序之多视频暂停播放,超出可视区域停止播放视频在自定义组件中实现案例

项目页面存在多个视频时,只播放视频可见范围内单个视频播放的解决方案

QQ录屏20240326175303

在自定义组件中无onPageScroll(e)监听页面滚动的函数所以在自定义组件中用<scroll-view>标签包裹所有组件(以下为WXML页面源码)

html 复制代码
<scroll-view scroll-y bindscroll="getScrollLength" style="height:{{scrollHeight*2+'rpx'}}">
<view class="content-box" wx:for="{{articleList}}" wx:key="i">
	<view class="userInfo-box">
		<!-- 用户头像 -->
		<image src="{{item.UserHeadImg}}" mode="" class="head-imag" class="user-image" />
		<view class="name-lab-box">
			<!-- 用户昵称 -->
			<view class="user-name">{{item.UserNickName}}</view>
			<!-- 用户标签 -->
			<view class="user-lab">标签</view>
		</view>
		<!-- 关注标签 -->
		<view class="follow-btn">
			+关注
		</view>
		<!-- 删除当前微博文章 -->
		<view class="user-del">
			<view>x</view>
		</view>
	</view>
	<!-- 内容区域 -->
	<view class="weibo-content">
		<view class="text-contrnt" catch:tap="navGo">{{item.WeiBoContent}}</view>
		<!-- 视频或图片区域 -->
		<view class="weibo-content-img-video">
			<block wx:if="{{item.WeiBoImg}}">
				<image wx:for="{{item.WeiBoImg}}" bind:tap="preview" data-urls="{{item.WeiBoImg}}" data-index="{{number}}" wx:key="i" wx:for-item="imgUrl" wx:for-index="number" class="weibo-content-img" src="{{imgUrl}}" mode="aspectFill" />
			</block>
			<block wx:if="{{item.WeiBoVideo}}">
				<video controls id="{{'video'+item.Id}}" autoplay="{{false}}" show-mute-btn controls="false" custom-cache='true' direction="0" class="weibo-content-video" src="{{item.WeiBoVideo}}" />
			</block>

		</view>
	</view>
	<!-- 点赞转发评论区域 -->
	<view class="woo-box">
		<view class="woo-img-box" bind:tap="launch">
			<image src="../../img/weibocontent/3.1转发.png" mode="" class="icon" />
			转发
		</view>
		<view class="woo-img-box">
			<image src="../../img/weibocontent/pinglun.png" mode="" class="icon" />
			评论
		</view>
		<view class="woo-img-box">
			<image src="../../img/weibocontent/dianzan.png" mode="" class="icon" />
			点赞
		</view>
	</view>
</view>
</scroll-view>

给每个存在<video>组件赋值唯一的id属性,且不能为纯数字id属性(不知道为啥不行,我刚开始用的纯数字,就是获取不到video的上下文)

定义组件属性列表用于接收自定义组件的父组件传过来的数据遍历

javascript 复制代码
 /**
   * 组件的属性列表
   */
  properties: {
    articleList: Array, //文章集合
  },

在自定义组件的初始数据中定义几个数据

javascript 复制代码
/**
   * 组件的初始数据
   */
  data: {
    videoList: [], // 用于存储视频集合
    scrollHeight: 0, //滚动视图(<scroll-view>组件的高度)高度
    scrollLength: 0, //滚动距离
  },

在自定义组件的生命周期声明对象(在组件视图布局完成后获得手机设备的屏幕可用高度,此代码中减去的83为在我本次项目中自定义组件的父组件导航的高度,所以自定义组件在父组件中可用高度为屏幕可用高度减去父组件中导航的高度)

javascript 复制代码
/* 组件生命周期声明对象 */

  lifetimes: {
    //组件在视图层布局完成后执行
    attached: async function () {
      var {
        windowHeight
      } = await wx.getSystemInfoSync();
      this.setData({
        scrollHeight: windowHeight - 83
      })
    }
  },

定义<scroll-view>组件的滚动事件监听,监听滚动的距离长度(if中的判断移动的距离长度大于200时才给赋值,可根据实际需要调整)

javascript 复制代码
//获得滚动长度
    getScrollLength(e) {
      if (e.detail.scrollTop - this.data.scrollLength > 200 || e.detail.scrollTop - this.data.scrollLength < -200) {
        this.setData({
          scrollLength: e.detail.scrollTop, //获得滚动距离
        })
        //控制视频播放和暂停
        this.getVideo();
      }
    },

函数getVideo()控制自定义组件中可见范围内的视频的播放和暂停

javascript 复制代码
//控制视频播放和暂停
    getVideo() {
      this.setData({
        videoList: []
      })//父组件在给自定义组件传值时都是传输的完整的新值,所以在每次执行函数时清空初始数据的值
      this.data.articleList.forEach(item => {
        if (item.WeiBoVideo) {
          this.setData({
            videoList: [...this.data.videoList, item]
          })
        }
      })//将父组件传输给自定义组件的的数据中找出存在item.WeiBoVideo的数据
      //将所有存在<video>组件的数据遍历并创建上下文  
      this.data.videoList.forEach(video => {
        var id = video.Id;
        const query = this.createSelectorQuery();//创建组件上下文
        //依据视频组件的id通过boundingClientRect()方法获得当前视频组件的相对位置(此方法为异步方法)
        query.select('#video' + id).boundingClientRect(rect => {
          //校验视频是否跑出范围(rect.top)意为距离滚轮组件顶部的距离,每次滚轮滚动后,此值都会发生变化
          if (rect.top <300&&rect.bottom>100) {
            // 视频在可视范围内,暂停它  
            this.playVideo(id);
          } else {
            // 视频在可视范围内,暂停它  
            this.pauseVideo(id);
          }
        }).exec();
      })
    },

此段代码中需要留意的就是boundingClientRect()此函数为异步函数,rect.top 、rect.bottom意为距离滚轮组件顶部的距离,每次滚轮滚动后,此值都会发生变化

视频播放函数及暂停函数(在自定义组件中需要添加this参数,不然无法控制自定义组件内部的播放和暂停)

javascript 复制代码
    //视频播放
    playVideo(id) {
      const video = wx.createVideoContext('video' + id,this);
      video.play();
    },
    //视频暂停
    pauseVideo(id) {
      const video = wx.createVideoContext('video' + id,this);
      video.pause();
    },
相关推荐
voipmaker8 小时前
GB28181 对接踩坑实录:注册不上、目录不全、流卡顿,一次说清(附 2022 版变更清单)
物联网·音视频·实时音视频·信息与通信·iot·gb28181·国标gb28181
ngaiwe9 小时前
AA我来算小程序实践:把付款人、承担人和结算状态分开建模
微信小程序
2601_9583529010 小时前
23.5×19mm 换掉一整条音频链?|A-68 集成了什么:ADC / DAC / 24.576MHz 时钟 / AEC / 波束降噪,主控仅需 6 根线
前端·音视频·ai降噪·回声消除·语音模块
2601_9654488710 小时前
AI视频制作:做系列历史人物视频音色不搭,AI 音色克隆的方法实测
人工智能·音视频
码上观世界10 小时前
多余的一声「嗯」:Fun-CosyVoice3 zero_shot 开头伪影排查实录
音视频
manyingAi11 小时前
AI漫剧生产系统架构解析:从文本拆解到音视频合成
人工智能·音视频
技灵AI15 小时前
MiniMax H3 能做哪些视频?商品广告、人物表演与运镜怎么选
人工智能·prompt·aigc·音视频
AIsoft_868917 小时前
职场音频文件怎么整理?录音APP有哪些用法
android·音视频
EasyCVR18 小时前
多厂区值守点分散,视频汇聚/视频融合/视频分析平台EasyCVR人员离岗AI监测怎么做才省事?
音视频·easycvr·国标gb28181
TK泰妞18 小时前
TikTok 商品视频有播放却没点击?从 4 个环节定位内容问题
音视频