2025年3月15日 星期六 甲辰(龙)年 月十四 设为首页 加入收藏
rss
您当前的位置:首页 > 计算机 > 编程开发 > Html+Div+Css(前端)

Vue3 中集成海康 H5 监控视频播放功能

时间:02-23来源:作者:点击数:17
CDSY,CDSY.XYZ

一、引言

随着视频监控技术的发展,许多应用场景需要集成实时视频监控功能。本文将详细介绍如何在 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 的一些核心函数,如 refonMountednextTick 等,以及 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>
  1. 初始化数据树
    • dataTree 和 dataTree1 是两个响应式数组,用于存储处理后的数据。
    • screenmonitoring 是一个引用,用于指向 ScreenMonitoring 子组件的实例。
    • defaultProps 是传递给子组件的默认属性配置。
  2. 组件挂载时
    • nextTick():等待 DOM 更新完成后再执行后续操作。
    • getTreeJson(params):从服务器获取数据,并处理返回的数据。
    • extractNameAndRebuildTree(item):递归处理每个节点,提取 name 并放在最外层。
  3. 处理点击事件
    • handleSpjkPOIClick(poiId, coord):当点击某个 时,获取对应的视频 URL 并初始化视频播放。
    • getGetByCodes(params):从服务器获取视频 URL 数据。
    • setTimeout(() => { ... }, 1):延迟 1 毫秒后初始化视频播放。

通过这种方式,父组件能够有效地初始化数据树,并在点击 树状 时触发视频播放。

本文旨在详细介绍如何在 Vue 3 应用中集成海康 H5 监控视频播放功能,实现视频的实时播放、分屏显示以及全屏切换等功能。

CDSY,CDSY.XYZ
方便获取更多学习、工作、生活信息请关注本站微信公众号城东书院 微信服务号城东书院 微信订阅号
推荐内容
相关内容
栏目更新
栏目热门
本栏推荐