解决微信小程序中,页面中多个视频只播放一个视频的方法

需求:在页面中只允许播放一个视频。

目标:在页面中同时展示多个视频,但只有一个视频可以播放,其他视频需要停止播放。

简介:

当在微信小程序中需要实现多个视频只播放一个视频时,我们面临了无法直接操作 DOM 的挑战。本文将介绍如何利用微信小程序的组件化开发和事件监听机制,以实现页面中多个视频的单一播放功能。通过使用组件化开发和事件监听,我们可以在一个页面中同时展示多个视频,并确保只有一个视频可以播放,其他视频会被停止。通过阅读本文,您将了解到针对微信小程序的具体实现方法,为您的项目提供实用的解决方案。

实现效果:

2.gif

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…

image-20230608151448358.png

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();
        }
    })
}

方法用于处理视频播放状态的变化。它接受两个参数:labelIdcallback。首先,它将labelIdcallback添加到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>
全部评论

相关推荐

10-09 22:05
666 C++
找到工作就狠狠玩CSGO:报联合国演讲,报电子烟设计与制造
点赞 评论 收藏
分享
点赞 收藏 评论
分享
牛客网
牛客企业服务