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

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

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();
    },
相关推荐
伊织code2 小时前
SmolVLM2 - 将视频理解带到每个设备
音视频·视觉·视频理解·小模型·smolvlm·端侧
—Qeyser3 小时前
用Deepseek写一个五子棋微信小程序
微信小程序·小程序
遇到困难睡大觉哈哈4 小时前
HarmonyOS 音频录制与播放模块
华为·音视频·harmonyos·鸿蒙
波波仔864 小时前
视频录像机视频通道是指什么
音视频·视频录像机·选型指标
余~~185381628004 小时前
【定制开发】碰一碰发视频系统定制开发,支持OEM
音视频
oil欧哟5 小时前
🥳 做了三个月的学习卡盒小程序,开源了!
前端·vue.js·微信小程序
weixin_486281456 小时前
webRTC实现一对一通话视频流程
音视频·webrtc
远方2.06 小时前
AI视频生成工具清单(附网址与免费说明)
人工智能·音视频
窝窝和牛牛11 小时前
记录小白使用 Cursor 开发第一个微信小程序(二):创建项目、编译、预览、发布(250308)
微信小程序·小程序
EasyCVR14 小时前
EasyRTC嵌入式视频通话SDK的跨平台适配,构建web浏览器、Linux、ARM、安卓等终端的低延迟音视频通信
android·arm开发·网络协议·tcp/ip·音视频·webrtc