Skip to content
本页目录

vue中使用h5 video标签实现弹窗播放本地视频

参考h5 < video >标签的用法 在开发过程中主要涉及到以下几个需要关注的点

1.弹窗的打开关闭

父组件中使用.sync绑定visible属性,可直接在子组件中关闭弹窗更新父组件传入的visible值;

html
// 父组件中引用子组件
<video-modal :visible.sync="showVideoModal">

// 子组件中
<el-dialog :visible="visible" @close="closeModal">

javascript
// 子组件中关闭弹窗方法
closeModal() {
    this.$emit("updata:visible", false);
}

不过这样使用会导致每次重新打开视频弹窗进度条都会留在上一次打开的位置,所以需要在引用子组件外再嵌套一个div,利用v-if使其每次打开都重新渲染,从而解决进度条缓存的问题;

html
<div v-if="showVideoModal">
    <video-modal :visible.sync="showVideoModal">
</div>

2. 本地视频资源路径的引入

需要播放的视频是项目中的静态资源,由于弹窗组件需要支持可复用,所以视频路径不可写死,下面示例为视频名称自定义;

html
<video
    ref="video"
    class="play-video"
    controls="controls"
    autoplay="autoplay"
>
    <source :src="require('@/assets/videos/' + videoName + '.mp4')" type="video/mp4" />
</video>

如果视频不在src目录下,而是public目录下则写法略有不同;

javascript
computed: {
    src() {
        // 需要在js部分用计算属性定义
        return process.env.BASE_URL + "videos/" + this.videoName + ".mp4";
    }
},

3. 视频播放完毕自动关闭弹窗

监听video标签的ended事件并关闭弹窗即可,vue生命周期中定义需要增加this.$nextTick,否则无法获取对应的dom元素;

javascript
mounted() {
    this.$nextTick(() => {
        // 播放完毕自动关闭弹窗
        const eleVideo = document.querySelector(".play-video");
        eleVideo.addEventListener("ended", () => {
            this.closeVideoModal();
        }, false);
    });
},

4. 视频在弹窗中自适应大小

给video标签设置合适的宽高,在利用object-fit: contain;属性即可。

最后附上完整代码

vue
<template>
    <el-dialog class="video-dialog" :visible="visible" :title="title" width="75%" append-to-body @close="closeVideoModal">
        <video
            ref="video"
            class="play-video"
            controls="controls"
            autoplay="autoplay"
        >
            <source :src="src" type="video/mp4" />
        </video>
    </el-dialog>
</template>

<script>
export default {
    name: "VideoModal",
    props: {
        visible: {
            type: Boolean,
            default: false
        },
        // 父组件传参弹窗标题
        title: {
            type: String,
            default: ""
        },
        // 父组件传参要播放的视频名称
        videoName: {
            type: String,
            default: ""
        }
    },
    computed: {
        src() {
            return process.env.BASE_URL + "videos/" + this.videoName + ".mp4";
        }
    },
    mounted() {
        this.$nextTick(() => {
            // 播放完毕自动关闭弹窗
            const eleVideo = document.querySelector(".play-video");
            eleVideo.addEventListener("ended", () => {
                this.closeVideoModal();
            }, false);
        });
    },
    methods: {
        closeVideoModal() {
            this.$emit("update:visible", false);
        }
    }
};
</script>

<style lang="scss" scoped>
.play-video {
    object-fit: contain;
    width: 100%;
    height: 99.5%;
}
</style>