组件描述

  • 背景
    elementui官方组件库没有视频相关的组件,于是自己封装了一个视频组件。el-video组件与el-image组件比较类似,总体在H5 video标签和el-dialog的基础上进行封装。
  • 实现的功能
    (1)可以自定义视频的大小

(2)可以自定义开启视频预览的功能类似el-image组件点击缩略图预览大图的效果
(3)支持自定义设置预览的视频,可以自己使用视频组件或者定义原生video组件进行预览视频的展示。默认使用设定好的视频预览。
(4)支持自定义视频加载错误时显示效果。

组件说明

属性

参数说明类型可选值默认值
widthvideo的宽度string---70(单位px)
heightvideo的高度string---70(单位px)
fit确定视频如何适应容器框,同原生 object-fitstringfill / contain / cover / none / scale-downnone
src视频的资源路径string------
customPreview是否自定义视频预览区域,需开启视频预览功能才生效booleanfalse/truefalse
enablePreview是否开启视频预览功能booleanfalse/truefalse
enableCustomEorror是否开启自定义加载错误内容booleanfalse/truefalse

事件

事件名称说明回调参数
openPreviewCallback预览模态框打开事件customPreview:是否为自定义预览
loadeddataCallback视频成功加载时的事件dom:当前视频的dom节点

插槽

名称说明
previewVideo视频区域的占位内容
customError视频加载错误的占位内容

组件源码

<template>
<div>
  <div class="el-video-box"  @click="viewVideo" :style="{'width':`${width}px`,'height':`${height}px`}" v-show="isLoaded">
    <video :width="width" :height="height"  :style="{'object-fit': fit}" ref="myvideo" crossorigin="anonymous">
      <source :src="src">

    </video>
    <img src='@/assets/images/play.png' style="position: absolute;" v-if="showPlayIcon"
         :style="{width:`${width/2}px`,height:`${height/2}px`,top: `${height/4}px`,left: `${width/4}px`}"/>
  </div>
  <div v-show="!isLoaded" class="el-video-box error-box"  @click="viewVideo" :style="{'width':`${width}px`,'height':`${height}px`}">
    <div v-if="enableCustomEorror">
      <slot name="customError"></slot>
    </div>
    <span class="errorIcon" v-else>加载失败</span>
  </div>
  <el-dialog  :visible.sync="showVideo"  :fullscreen="true" class="videoDialog">
    <div style="margin: 100px auto;width: 800px;height: 600px;" v-if="!customPreview">
      <video width="800" height="600" controls ref="video" crossorigin="anonymous">
        <source :src="src">
      </video>
    </div>
    <div v-if="customPreview">
      <slot name="previewVideo">
      </slot>
    </div>
  </el-dialog>
</div>
</template>

<script>
export default {
  name: "video",
  props:{
    width:{
      type:String,
      default:60
    },
    height:{
      type:String,
      default:60
    },
    fit:{
      type:String,
      default:'none'
    },
    src:{
      type:String,
      default:''
    },
    customPreview:{
      type:Boolean,
      default:false
    },
    enablePreview:{
      type:Boolean,
      default:false
    },
    enableCustomEorror:{
      type:Boolean,
      default:false
    }
  },
  data(){
    return{
      showVideo:false,
      showPlayIcon:true,
      isLoaded:false,
    }
  },
  mounted() {
     this.$refs.myvideo.addEventListener('loadedmetadata',()=>{
        this.isLoaded=true
        this.$emit('loadeddataCallback',this.$refs.myvideo)
      })
  },
  computed:{

  },
  watch:{
    showVideo:function(newVal){
     if(newVal){
       this.$nextTick(()=>{
         this.$refs.video && this.$refs.video.load()
       })
     }
    }
  },
  methods:{
    viewVideo(){
      if(this.enablePreview&&this.isLoaded){
        this.showVideo=true
          this.$emit('openPreviewCallback',this.customPreview)
      }else{
        if(this.$refs.myvideo.paused){
          this.showPlayIcon=false
          this.$refs.myvideo.play()
        }else{
          this.$refs.myvideo.pause()
          this.showPlayIcon=true
        }
      }

    }
  }
}
</script>

<style scoped>
.videoDialog /deep/ .el-dialog__headerbtn{
  top: 50px;
  right: 70px;
  background: rgba(102, 104, 107,0.6);
  cursor: pointer;
  font-size: 24px;
  width: 45px;
  height: 45px;
  border-radius: 50%;
  border: 1px solid gray;
}
.videoDialog /deep/ .el-dialog.is-fullscreen{
  background: rgba(0,0,0,0.05);
}
.videoDialog /deep/ .el-dialog__headerbtn .el-dialog__close{
  color: whitesmoke;
}
.videoDialog /deep/ .el-dialog__headerbtn .el-dialog__close:hover{
  color: whitesmoke;
}
.el-video-box{
  position: relative;
  cursor: pointer;
  border: 1px solid lightgrey;
}
.errorIcon{
  font-size: 12px;
  vertical-align: middle;
  color: gray;
}
.error-box{
  line-height: 70px;
  text-align: center;
}
</style>

组件使用

     <el-video  :src="problemInfo.videoUrl" ref="myvideo" 
                          fit="fill" width="70" height="70" :enablePreview="true" :customPreview="true">
                     <div slot="previewVideo" style="margin: 100px auto;width: 800px;height: 600px;">
                       <video  width="800" height="600" controls ref="video"  crossorigin="anonymous">
                         <source :src="problemInfo.videoUrl">
                       </video>
                     </div>
                </el-video>

组件效果

效果同el-image组件查看预览效果类似

该视频组件主要作用为展示和预览,其他更多功能可以自定义video进行拓展,有更多实用功能欢迎指正!

参考

菜鸟教程

最后修改:2022 年 06 月 08 日
如果觉得我的文章对你有用,请随意赞赏