Vue3 中集成海康 H5 监控视频播放功能
🌈个人主页:前端青山
🔥系列专栏:Vue篇
🔖人终将被年少不可得之物困其一生
依旧青山,本期给大家带来Vuet篇专栏内容:Vue-集成海康 H5 监控视频播放功能
目录
一、引言
随着视频监控技术的发展,许多应用场景需要集成实时视频监控功能。本文将详细介绍如何在 Vue 3 应用中集成海康 H5 监控视频播放功能,实现视频的实时播放、分屏显示以及全屏切换等功能。
二、环境搭建
为了确保代码能够正常运行,我们需要准备以下开发环境:
-
Vue 3:用于构建前端应用。
-
Element Plus:用于 UI 组件库。
-
海康 H5 SDK:用于播放视频流。
三、代码解析
子组件部分
<template>
<div class="play_windows" v-loading="loading" element-loading-background="rgba(122, 122, 122, 0.8)">
<div class="tree-form">
<el-tree
ref="tree"
:data="dataTree"
:props="defaultProps"
:highlight-current="true"
@node-click="pitchOns"
>
<template #default="{ node, data }">
<span class="custom-tree-node">
{{ data.name }}
</span>
</template>
</el-tree>
</div>
<div class="video">
<div class="dialog-slot-video-header-right">
<el-button class="myButton" :class="{ 'active': videoIndex == 4 }" @click="videoTabClick(4)">1×1</el-button>
<el-button class="myButton" :class="{ 'active': videoIndex == 1 }" @click="videoTabClick(1)">3×3</el-button>
<el-button class="myButton" :class="{ 'active': videoIndex == 2 }" @click="videoTabClick(2)">4×4</el-button>
<el-button class="myButton" :class="{ 'active': videoIndex == 3 }" @click="videoTabClick(3)">整体全屏</el-button>
</div>
<div id='corpvideo'></div>
</div>
</div>
</template>
-
功能说明
-
play_windows
容器:包含两个主要部分,左侧为树形结构,右侧为视频播放区域。 -
el-tree
组件:展示监控设备树形结构,点击节点触发pitchOns
方法。 -
视频播放区域:通过按钮控制不同的分屏模式(1×1、3×3、4×4)及全屏模式。
-
id='corpvideo'
:指定视频播放容器的 ID,供 H5 SDK 使用。
-
1. 导入模块和组件
import { ref, onMounted, nextTick, defineProps, defineExpose, defineEmits, watch, onBeforeUnmount } from 'vue';
import { ElMessage } from 'element-plus';
import { videoallList } from '@/api/screenVideo/index';
import { getGetByCode } from '@/api/videoSurveillance/index';
-
功能说明:导入了 Vue 的一些核心函数,如
ref
、onMounted
、nextTick
等,以及 Element Plus 的消息提示组件ElMessage
和相关 API。
2. 定义组件属性和事件
const emit = defineEmits(["handleSpjkPOIClick"]);
const props = defineProps({
playURL: String, // 视频 URL
splitNum: Number, // 分屏播放,默认最大分屏 4*4
dataTree: Object, // 树形数据
defaultProps: Object
});
-
功能说明:定义了组件的属性
props
和自定义事件emit
,用于接收父组件传递的数据和触发事件。
3. 初始化变量
let dataTree = ref<any>(props.dataTree);
let defaultProps = ref<any>(props.defaultProps);
let loading = ref<Boolean>(false);
let myPlugin = ref<any>(null);
let index = ref<any>(1); // 多屏播放显示第几个
let mode = ref<any>(1); // 0 为低级播放,1 为高级播放
const urlList = ref<any>([]);
let playURLs = ref<any>("");
const jsPlugin = (window as any).JSPlugin;
-
功能说明:定义了一些响应式变量,用于存储数据和状态,如
loading
用于控制加载状态,myPlugin
用于存储视频插件实例。
4. 初始化视频插件
const myPlugins = () => {
myPlugin.value = new jsPlugin({
szId: 'corpvideo', // 需要英文字母开头,唯一性,必填
szBasePath: '/h5player', // 必填,与 h5player.min.js 的引用目录一致
bSupporDoubleClickFull: true, // 是否支持双击全屏,默认 true
iMaxSplit: 4, // 分屏播放,默认最大分屏 4*4
iCurrentSplit: splitNum.value,
oStyle: {
borderSelect: '#FFCC00',
},
openDebug: true,
});
};
-
功能说明:定义了一个方法
myPlugins
,用于初始化视频插件实例,并配置相关参数。
5. 控制分屏数量
const tabPosition = ref<any>(1);
const playBackNum = (num: any) => {
if (num == "3") {
myPlugin.value.JS_FullScreenDisplay(true).then(
() => { console.log(`wholeFullScreen success`) },
(e: any) => { console.error(e) }
);
return;
}
if (num == splitNum.value) {
return;
}
splitNum.value = num;
};
-
功能说明:定义了一个方法
playBackNum
,用于控制分屏数量,并支持全屏显示。
6. 视频线路弹框按钮
const splitNum = ref<any>(1);
const videoIndex = ref<number>(4); // 视频信息弹框默认值 index
const videoTabClick = (type: number) => {
videoIndex.value = Number(type);
if (type == 1) {
splitNum.value = 3;
const totalWindows = splitNum.value * splitNum.value;
for (let i = 0; i < totalWindows; i++) {
const url = urlList.value[i] || urlList.value[0];
myPlugin.value.JS_Play(url, { playURL: url, mode: mode.value }, i).then(
() => console.log(`Playing in window ${i}`),
(e: any) => console.error('Error playing video', e)
);
}
} else if (type == 2) {
splitNum.value = 4;
const totalWindows = splitNum.value * splitNum.value;
for (let i = 0; i < totalWindows; i++) {
const url = urlList.value[i] || urlList.value[0];
myPlugin.value.JS_Play(url, { playURL: url, mode: mode.value }, i).then(
() => console.log(`Playing in window ${i}`),
(e: any) => console.error('Error playing video', e)
);
}
} else if (type == 3) {
myPlugin.value.JS_FullScreenDisplay(true).then(
() => { console.log(`wholeFullScreen success`) },
(e: any) => { console.error(e) }
);
return;
} else if (type == 4) {
splitNum.value = 1;
}
myPlugin.value.JS_ArrangeWindow(splitNum.value).then(
() => { console.log(`arrangeWindow to ${splitNum.value}x${splitNum.value} success`) },
(e: any) => { console.error(e) }
);
console.log(splitNum.value, '监控视频的值');
};
-
功能说明:定义了一个方法
videoTabClick
,用于控制视频线路弹框按钮,并根据不同的类型调整分屏数量和播放视频。
7. 生命周期钩子
onMounted(() => {
nextTick(() => {
myPlugins();
// 事件回调绑定
myPlugin.value.JS_SetWindowControlCallback({
windowEventSelect: function (iWndIndex: any) { // 插件选中窗口回调
console.log('windowSelect callback: ', iWndIndex);
},
pluginErrorHandler: function (iWndIndex: any, iErrorCode: any, oError: any) { // 插件错误回调
console.log('pluginError callback: ', iWndIndex, iErrorCode, oError);
},
windowEventOver: function (iWndIndex: any) { // 鼠标移过回调
// console.log(iWndIndex);
},
windowEventOut: function (iWndIndex: any) { // 鼠标移出回调
// console.log(iWndIndex);
},
windowEventUp: function (iWndIndex: any) { // 鼠标mouseup事件回调
// console.log(iWndIndex);
},
windowFullCreenChange: function (bFull: any) { // 全屏切换回调
console.log('fullScreen callback: ', bFull);
},
firstFrameDisplay: function (iWndIndex: any, iWidth: any, iHeight: any) { // 首帧显示回调
console.log('firstFrame loaded callback: ', iWndIndex, iWidth, iHeight);
},
performanceLack: function () { // 性能不足回调
console.log('performanceLack callback: ');
}
});
});
});
onBeforeUnmount(() => {
console.log('切换了');
});
-
功能说明:在组件挂载时初始化视频插件,并绑定事件回调。在组件卸载前执行清理操作。
8. 初始化视频播放
const initialize = (playURL: any, urls?: any[]) => {
urlList.value = urls;
playURLs.value = playURL;
loading.value = true;
index.value = myPlugin.value.currentWindowIndex;
myPlugin.value.JS_Play(playURL, { playURL, mode: mode.value }, index.value).then(
() => { loading.value = false }, // 成功操作
(e: any) => {
loading.value = false;
ElMessage.error('监控视频异常'); // 失败操作
}
);
};
-
功能说明:定义了一个方法
initialize
,用于初始化视频播放,并处理加载状态和错误提示。
9. 处理事件
const pitchOns = (e: any) => {
if (!e || !e.self) {
if (e.equipmentCoding) {
handleAddChild(e);
}
return;
}
if (e.children) {
emit("handleSpjkPOIClick", e.self.indexCode, '');
return;
} else {
handleAddChild(e);
}
};
const handleAddChild = (e: any) => {
if (!e || !e.self) {
if (e.equipmentCoding) {
videoUrl(e.equipmentCoding);
}
return;
}
if (e.self.indexCode) {
let params = {
UnitIndexCode: e.self.indexCode,
};
videoallList(params).then((res: any) => {
if (res.data.rows.length == 0) {
emit("handleSpjkPOIClick", e.self.indexCode, '');
} else {
e.children = e.children || [];
// 修改 res.data.rows 中所有数据对象的字段 equipmentName 变成 name
res.data.rows = res.data.rows.map((child: any) => ({
...child,
name: child.equipmentName, // 将 equipmentName 字段复制到 name 字段
// 删除原 equipmentName 字段
}));
res.data.rows.forEach((child: any) => {
e.children.push(child);
});
// 展开当前节点
(e as any).expanded = true;
}
})
}
}
10.调用插件播放
const videoUrl =(e:any)=>{
let params = {
equipmentCoding: e,
};
getGetByCode(params).then(res => {
setTimeout(() => {
initialize(res.data.url);
}, 1);
});
}
// 使用 watch 监听 splitNum 的变化
watch(splitNum, (newValue, oldValue) => {
if (newValue !== oldValue) {
myPlugins();
myPlugin.value.JS_ArrangeWindow(splitNum.value).then(
() => { console.log(`arrangeWindow to ${splitNum.value}x${splitNum.value} success`) },
(e: any) => { console.error(e) }
)
}
});
//最后暴露方法
defineExpose({
initialize,
myPlugins
})
父组件调用
<template>
<div>
<ScreenMonitoring ref="screenmonitoring" :dataTree="dataTree" :defaultProps="defaultProps" @handleSpjkPOIClick="handleSpjkPOIClick" />
</div>
</template>
<script setup>
import { ref, onMounted, nextTick } from 'vue';
const dataTree = ref<any>([]);
const dataTree1 = ref<any>([]);
let screenmonitoring = ref();
const defaultProps = {
children: 'children',
label: 'name',
};
onMounted(() => {
nextTick(() => {
let params = {};
getTreeJson(params).then((res: any) => {
let list = res.rows[0].children[9].children;
list.forEach((item: any) => {
extractNameAndRebuildTree(item); // 对每个根节点执行递归提取
});
dataTree.value = list; // 将处理后的列表赋值给 dataTree
});
});
});
const extractNameAndRebuildTree = (node: any) => {
// 如果节点有 self,提取 name 并放在最外层
if (node.self && node.self.name) {
node.name = node.self.name;
}
// 如果节点有 children,递归处理每个子节点
if (node.children && node.children.length > 0) {
node.children.forEach((child: any) => {
extractNameAndRebuildTree(child);
});
}
};
const handleSpjkPOIClick = (poiId: string, coord: string) => {
let params = {
UnitIndexCode: poiId,
};
getGetByCodes(params).then((res: any) => {
setTimeout(() => {
screenmonitoring.value.initialize(res.data.urls[0], res.data.urls);
}, 1);
});
};
</script>
-
初始化数据树:
-
dataTree
和dataTree1
是两个响应式数组,用于存储处理后的数据。 -
screenmonitoring
是一个引用,用于指向ScreenMonitoring
子组件的实例。 -
defaultProps
是传递给子组件的默认属性配置。
-
-
组件挂载时:
-
nextTick()
:等待 DOM 更新完成后再执行后续操作。 -
getTreeJson(params)
:从服务器获取数据,并处理返回的数据。 -
extractNameAndRebuildTree(item)
:递归处理每个节点,提取name
并放在最外层。
-
-
处理点击事件:
-
handleSpjkPOIClick(poiId, coord)
:当点击某个 时,获取对应的视频 URL 并初始化视频播放。 -
getGetByCodes(params)
:从服务器获取视频 URL 数据。 -
setTimeout(() => { ... }, 1)
:延迟 1 毫秒后初始化视频播放。
-
通过这种方式,父组件能够有效地初始化数据树,并在点击 树状 时触发视频播放。
本文旨在详细介绍如何在 Vue 3 应用中集成海康 H5 监控视频播放功能,实现视频的实时播放、分屏显示以及全屏切换等功能。
原文地址:https://blog.csdn.net/2302_76329106/article/details/142491419
免责声明:本站文章内容转载自网络资源,如本站内容侵犯了原著者的合法权益,可联系本站删除。更多内容请关注自学内容网(zxcms.com)!