解决微信小程序中,页面中多个视频只播放一个视频的方法
需求:在页面中只允许播放一个视频。
目标:在页面中同时展示多个视频,但只有一个视频可以播放,其他视频需要停止播放。
简介:
当在微信小程序中需要实现多个视频只播放一个视频时,我们面临了无法直接操作 DOM 的挑战。本文将介绍如何利用微信小程序的组件化开发和事件监听机制,以实现页面中多个视频的单一播放功能。通过使用组件化开发和事件监听,我们可以在一个页面中同时展示多个视频,并确保只有一个视频可以播放,其他视频会被停止。通过阅读本文,您将了解到针对微信小程序的具体实现方法,为您的项目提供实用的解决方案。
实现效果:
H5、Web等操作方法
无论使用哪种语言,都可以轻松地获取document
对象。
要在网页中实现一个页面上有两个视频,点击一个视频后另一个视频暂停的功能,可以使用 JavaScript 和 HTML5 Video API 来实现。
可以为每个视频元素添加一个唯一的标识符(例如ID),然后通过 JavaScript 控制视频的播放状态。通过监听视频元素的点击事件,当点击一个视频时,首先暂停另一个视频,然后播放当前点击的视频。
以下是具体的实现方式:
方法一
使用 Vue 框架时,可以使用 ref
获取视频元素的引用,并通过方法来控制视频的播放状态。
HTML 代码:
<video ref="videoRef1" src="video1.mp4" controls @play="watchPlay('videoRef1')"></video>
<video ref="videoRef2" src="video1.mp4" controls @play="watchPlay('videoRef2')"></video>
Vue 方法:
methods: {
watchPlay(id) {
// 被点击了播放
if (id === "videoRef1") {
this.$refs.videoRef2.pause();
} else {
this.$refs.videoRef1.pause();
}
},
},
方法二
使用原生 JavaScript 可以通过获取唯一的 DOM 元素来控制视频的播放状态。
HTML 代码:
<video id="video1" src="video1.mp4" controls></video>
<video id="video2" src="video2.mp4" controls ></video>
JavaScript 代码:
var video1 = document.getElementById('video1');
var video2 = document.getElementById('video2');
video1.addEventListener('click', function() {
if (!video1.paused) {
video1.pause();
}
if (video2.paused) {
video2.play();
}
});
video2.addEventListener('click', function() {
if (!video2.paused) {
video2.pause();
}
if (video1.paused) {
video1.play();
}
});
这样,当点击一个视频时,另外的视频会暂停播放。
注意:
如果在微信小程序中,就有很大的问题,微信中没有所谓的DOM概念,我们无法用该方法去处理这些问题,
微信小程序为什么不存在DOM的概念
微信小程序采用的是基于组件的开发模式,与传统的网页开发有所不同,因此不存在传统意义上的 DOM(文档对象模型)概念。
在网页开发中,DOM 是用于表示和操作文档结构的 API,可以通过 JavaScript 操作 HTML 元素、修改样式、添加事件监听等。而在微信小程序中,使用的是组件化的开发方式,开发者通过编写组件来构建小程序页面。
微信小程序中的组件是由微信小程序框架提供的,每个组件都有自己的结构、样式和行为。开发者可以根据需要,使用预定义的组件或自定义组件来构建小程序页面。组件具有封装的特性,包括自己的视图层和逻辑层,不同组件之间相互独立,可以进行复用和组合。
与传统的网页开发相比,微信小程序的开发更注重于组件的概念和组件之间的通信。开发者通过在页面中引用组件、编写组件的逻辑和样式来实现页面的功能。页面和组件的关系更像是一种组件的组合,而不是通过 DOM 操作来实现页面的构建和交互。
因此,微信小程序中没有直接操作 DOM 的概念,开发者主要通过操作组件的属性、事件和数据来实现页面的交互和动态更新。
我们该怎么办
考虑到微信Dom的不可操作问题,我们最好使用的就是:页面间通信
为了区分不同的组件,给每一个组件,传递辨别的ID,利用ID通过createVideoContext去创建独一无二的 video上下文VideoContext对象。
uni语法:uniapp.dcloud.net.cn/api/media/v…
this.videoContext = uni.createVideoContext('myVideo', this)
以下方法供大家参考
<video
controls
autoplay
@play="watchPlay"
enable-play-gesture
class="video"
:id="'video'+labelId"
:src="videoInfo.url"> </video>
enable-play-gesture
是一个微信小程序的视频组件属性,用于启用视频播放手势。当该属性设置为 true
时,用户可以通过滑动手势来控制视频的播放和暂停。
enable-play-gesture
属性只在微信小程序中生效,对于其他平台或环境可能不具备相同的效果。
为了避免直接操作 DOM,我们可以采用监听事件的方式来实现。具体来说,我们可以监听视频组件的
play
事件。
在初始化时,我们可以编写相应的处理函数来处理视频的播放。
使用uni去写,uni.createVideoContext具有更强的兼容性。
如果使用wx.createVideoContext
是在原生微信小程序中提供的方法,功能与 uni.createVideoContext
类似,也是用于创建视频上下文对象。
// 处理播放
handlePlayVideo(){
this.$nextTick(()=>{
this.videoRefData = uni.createVideoContext("video"+this.labelId, this);
this.videoRefData.play()
})
},
一旦有任何一个视频开始播放,就通过触发事件向父组件发送消息,以通知父组件执行相应的操作。
watchPlay(e){
// 发射出labelId,与handlePause这个函数
this.$emit("videoPlayState",this.labelId,this.handlePause)
},
// 处理暂停
handlePause(){
if(this.isShowVideo){
this.videoRefData.pause();
}else{
// console.log("该视频还没有被打开");
}
},
在父组件中使用时,可以处理视频被点击之后的事件。
<VideoPreviewCard @videoPlayState="videoPlayState" labelId="1"/>
<VideoPreviewCard @videoPlayState="videoPlayState" labelId="2"/>
处理方法:
pauseFunc:[]
---------------------------------
videoPlayState(labelId,callback){
this.pauseFunc.push({
labelId:labelId,
callback:callback
})
this.pauseFunc.forEach(item =>{
if(item.labelId != labelId){
item.callback();
}
})
}
方法用于处理视频播放状态的变化。它接受两个参数:labelId
和callback
。首先,它将labelId
和callback
添加到pauseFunc
数组中。然后,通过遍历pauseFunc
数组,对于除当前labelId
外的每个项,调用相应的callback
函数进行暂停操作。
实例
给出一组实例
子组件
子组件 VideoPreviewCard.vue
<template>
<view class="video_preview" >
<view v-if="!isShowVideo" class="video_preview_card" @click="handlePlayVideo">
<image class="video_preview_card_bg" :src="videoInfo.poster"></image>
</view>
<view v-else class="video_preview_play">
<video
@play="watchPlay"
enable-play-gesture
:id="'video'+labelId"
controls
autoplay
:src="videoInfo.url"> </video>
</view>
</view>
</template>
<script>
export default {
props:{
labelId:{
type:Number,
default: -1,
required: true
},
videoInfo:{
type:Object,
default:()=>{
return {}
}
}
},
data() {
return {
isShowVideo:false,
videoRefData:null
}
},
methods: {
handlePlayVideo(){
this.isShowVideo = true;
this.$nextTick(()=>{
this.videoRefData = uni.createVideoContext("video"+this.labelId,this);
this.videoRefData.play()
})
},
watchPlay(e){
this.$emit("videoPlayState",this.labelId,this.handlePause)
},
handlePause(){
if(this.isShowVideo){
this.videoRefData.pause();
}else{
// console.log("该视频还没有被打开");
}
},
}
}
</script>
父组件使用
<template>
<view class="earn_money_tutorial">
<VideoPreviewCard
@videoPlayState="videoPlayState"
:labelId="1"
/>
<VideoPreviewCard
@videoPlayState="videoPlayState"
:labelId="2"
/>
<VideoPreviewCard
@videoPlayState="videoPlayState"
:labelId="3"
/>
</view>
</template>
<script>
import VideoPreviewCard from "./components/earnMoneyTutorial/VideoPreviewCard.vue";
export default {
components:{
VideoPreviewCard
},
data() {
return {
pauseFunc:[]
}
},
methods: {
videoPlayState(labelId,callback){
this.pauseFunc.push({
labelId:labelId,
callback:callback
})
// 开播
this.pauseFunc.forEach(item =>{
if(item.labelId != labelId){
item.callback();
}
})
}
}
}
</script>