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

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

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();
    },
相关推荐
安步当歌1 小时前
【WebRTC】视频发送链路中类的简单分析(下)
网络·音视频·webrtc·视频编解码·video-codec
lqj_本人2 小时前
鸿蒙next版开发:音频并发策略扩展(ArkTS)
音视频
计算机-秋大田2 小时前
基于微信小程序的农场管理系统的设计与实现,LW+源码+讲解
java·spring boot·微信小程序·小程序·vue
2401_8441379514 小时前
PHP中小学优校管理系统小程序源码
微信·微信小程序·小程序·微信公众平台·微信开放平台
红米饭配南瓜汤16 小时前
WebRTC视频 04 - 视频采集类 VideoCaptureDS 中篇
音视频·webrtc·媒体
iSee85717 小时前
美团代付微信小程序 read.php 任意文件读取漏洞复现
微信小程序·小程序·php
fasewer18 小时前
notepad++下载安装教程
notepad++
杨武博19 小时前
音频格式转换
android·音视频
Learning改变世界20 小时前
ubuntu24.04播放语音视频
音视频
棱角~~21 小时前
10款PDF合并工具的使用体验与推荐!!
经验分享·其他·音视频·实时音视频·学习方法