组件代码
<template>
<div class="my-video" @click = videoClick>
<div class="flex_center video-box bg-black" v-show="!videoObj[src]">请检查视频地址!</div>
<div v-show="videoObj[src]" class="flex-center video-box" ref="videoPlayerContainer">
</div>
</div>
</template>
<script>
import {defineComponent, onMounted, onUnmounted, reactive, ref, toRefs, watch} from 'vue';
import 'video.js/dist/video-js.css';
import videojs from 'video.js';
export default defineComponent({
name: 'MyMonitor',
props: {
videoObj: {
type: Object,
default: {}
},
src: {
type: String,
default:''
},
},
emits:['videoClick'],
setup(props, {emit}) {
let videoPlayerContainer = ref();
let playerIns = null;
const state = reactive({
videoId: 0,
videoClick(){
emit('videoClick',props.videoObj)
},
createVideo() {
if (!playerIns) {
let videoOptions = {
controls: true,//开启交互,即是用户可控。
muted: true,//开启视频时是否静音
fluid: true,//根据外层css样式大小,自动填充宽高!比较实用,可搭配响应式
reload: "auto",//重载
}
let video = document.createElement('video');
video.className = 'video-js';
video.autoplay = false;
video.muted = true;
videoPlayerContainer.value.appendChild(video);
playerIns = videojs(video, videoOptions, function onPlayerReady() {
});
playerIns.on(['touchend','tap', 'click'],()=>{
emit('videoClick',props.videoObj)
})
}
playerIns.src({
src: props.videoObj[props.src],
type: "application/x-mpegURL"
})
},
disposeVideo() {
if (playerIns) {
playerIns.dispose();
playerIns = null;
}
},
})
watch(()=>props.videoObj,()=>{
props.videoObj[props.src]&&state.createVideo()
})
onMounted(() => {
props.videoObj[props.src]&&state.createVideo()
})
onUnmounted(()=>{
state.disposeVideo();
})
return {
...toRefs(state),
videoPlayerContainer,
}
}
})
</script>
<style lang="less" scoped>
.my-video,.video-box {
width: 100%;
height: 100%;
color:#fff;
:deep(.vjs-modal-dialog-content),.bg-black {
background: black;
}
:deep(.video-js .vjs-control){
width: 2em;
font-size:12px;
}
:deep(.video-js .vjs-modal-dialog){
overflow: hidden;
}
:deep(.video-js .vjs-time-control){
margin-right:25px;
}
:deep(.video-js .vjs-picture-in-picture-control){
margin-right:10px;
}
:deep(.vjs-fullscreen-control.vjs-control.vjs-button){
//display: none!important;
}
:deep(.video-js .vjs-progress-control .vjs-progress-holder){
}
:deep(.vjs-progress-control.vjs-control){
//max-width: 40px;
}
:deep(.vjs_video_3-dimensions.vjs-fluid:not(.vjs-audio-only-mode)),:deep(.vjs-fluid:not(.vjs-audio-only-mode)) {
padding-top: unset;
}
:deep(.video-js) {
height: 100%;
width: 100%;
overflow: hidden;
}
}
</style>
引用页面代码
<div class="videos-item" v-for="(item,index) in videos.list" :key="index">
<MyMonitor
:videoObj="item"
src="liveAddress"
@videoClick="state.videoClick"
/>
</div>
videos:{
title:'实时视频',
list:[],
async getVideoList(){
let res = await projectHome.getVideoList()
if((res?.code===requestCode)&&res.data.length>0) {
state.videos.list = []
res.data.forEach((item, index) => {
index<9&&state.videos.list.push(...item.channels)//默认最多只显示9个
})
}else{
state.videos.list=[]
}
}
},