Vue+Openlayers+HIKVSION实现点击摄像头进行预览

场景

SpringBoot+Vue+HIKVSION实现摄像头多选并多窗口预览(插件版):

SpringBoot+Vue+HIKVSION实现摄像头多选并多窗口预览(插件版)_霸道流氓气质的博客-CSDN博客

上面实现的摄像头的预览,是在菜单中配置摄像头参数,然后点击预览按钮时进行预览。

摄像头信息的新增和编辑包括在地图上添加和修改摄像头的坐标参考如下

SpringBoot+Vue+Openlayers实现地图上新增和编辑坐标并保存提交:

SpringBoot+Vue+Openlayers实现地图上新增和编辑坐标并保存提交_霸道流氓气质的博客-CSDN博客

在上面的基础上实现的效果如下

注:

博客:
霸道流氓气质的博客_CSDN博客-C#,架构之路,SpringBoot领域博主
关注公众号
霸道的程序猿
获取编程相关电子书、教程推送与免费下载。

实现

1、后台逻辑

定时任务中查询所有摄像头的坐标和ip、用户名、密码、端口等信息。

为了避免频繁对msyql数据库操作,可以借助于redis缓存的实现。

SpringBoot中通过自定义缓存注解(AOP切面拦截)实现数据库数据缓存到Redis:

SpringBoot中通过自定义缓存注解(AOP切面拦截)实现数据库数据缓存到Redis_霸道流氓气质的博客-CSDN博客

然后后台通过websocket推送给前端。

2、前端收到数据之后将摄像头图标添加显示

            if (data.video && data.video.length > 0) {
                await this.videoLayer.getSource().clear();
                this.drawVideoPoint(data.video);
                this.videoListData = data.video;
            }

每次收到新的数据重新新增feature,要将该图层的source清理一下。

在收到推送的数据的回调方法中判断数据不为0,则调用绘制点位的方法,并且将摄像头的数据存储一份给this.videoListData 。

接收的数据结构如下

 

3、添加点的方法drawVideoPoint实现

        drawVideoPoint(data) {
            // 画起点,终点
            data.forEach((item, index) => {
                var feature = new Feature({
                    geometry: new Point(item.videoAdd),
                });
                feature.setId(`video_${item.id}`);
                let url = "images/video.png";
                const zoom = this.map.getView().getZoom();
                let style = new Style({
                    image: new Icon({
                        scale: 0.06 * (zoom - 13),
                        src: url,
                        anchor: [0.48, 0.52],
                    }),
                    });
                feature.setStyle(style);
                this.videoLayer.getSource().addFeature(feature);
            });
        },

在添加每一个feature时一定要设置其id

feature.setId(`video_${item.id}`);

4、监听地图的点击事件

            // 监听地图点击事件
            self.onShow = self.map.on("singleclick", (evt) => {
                self.mapDialog(evt);
            });

5、点击事件方法实现

获取点击的feature

                    var feature = self.map.forEachFeatureAtPixel(evt.pixel, (feature) => {
                            return feature;
                        }
                    );

然后遍历上面存储的摄像头的数据对比id是否一致,获取对应feature的摄像头的属性

                        self.videoListData.forEach(async (e) => {
                            if (self.searchEmpId == 'video_'+ e.id) {
                                    let openVideoData = [];
                                    let hkvInfo = {
                                        ip: e.ip, //海康威视摄像头/硬盘录像机的ip地址
                                        port: e.port, //海康威视摄像头/硬盘录像机的端口
                                        username: e.username, //海康威视摄像头/硬盘录像机的用户名
                                        password: e.password, //海康威视摄像头/硬盘录像机的密码
                                        channels: [], //海康威视摄像头/硬盘录像机的通道
                                    };
                                    openVideoData.push(hkvInfo);
                                    let routeUrl = this.$router.resolve({
                                    path: "/carVideo",
                                    query: {
                                        videoData: JSON.stringify(openVideoData),
                                    },
                                });
                                window.open(routeUrl.href, "_blank");
                            }
                        });

然后将预览摄像头所需的参数传递到新的路由页面并在新的标签页中打开。

6、在router下index.js中添加/carVideo路由

    {
        path: '/carVideo',
        component: Layout,
        component: (resolve) => require(['@/views/runcontrolmange/carVideo/component/video'], resolve),
        meta: {title: '摄像头'},
        hidden: true,
    },

 

7、来到预览摄像头的页面video.vue

此页面实现预览的逻辑可以参考上面第一篇博客,下面附代码

<template>
  <div class="video_box">
    <!-- 摄像头 -->
    <div id="divPlugin" class="plugin"></div>
  </div>
</template>

<script>
import { WebVideoCtrl } from "/static/webVideoCtrl.js";
export default {
  name: "OpUser",
  components: {},
  data() {
    return {
      szInfo: "",
      rowList: {},
      hkvInfo: {},
      mySelectWnd: 0, //当前选中的窗口
      g_bPTZAuto: false,
      iProtocol: 1,
      loginLoading: false,
      startPlayLoading: false,
      bZeroChannel: false,
      iRtspPort: 0,
      index: 0,
      iWndowType: null,
      videoData: [],
    };
  },
  created() {

    this.videoData = JSON.parse(this.$route.query.videoData);
    if (this.videoData.length <= 1) {
      this.iWndowType = 1;
    } else if (this.videoData.length > 1 && this.videoData.length <= 4) {
      this.iWndowType = 2;
    }
  },
  mounted() {
    this.videoChange();
  },
  destroyed() {
    this.clickStopRealPlay();
    this.onLogout();
  },
  methods: {
    getList() {

    },
    videoChange() {
      setTimeout(() => {
        this.videoInitPlugin(); // 初始化video界面
      }, 300);
    },
    handleSelectionChange() {},
    submitForm() {},
    cancel() {},
    // 登录
    async onLogin() {
      var that = this;
      that.loginLoading = true;
      // 登录设备
      WebVideoCtrl.I_Login(
        that.hkvInfo.ip,
        that.iProtocol,
        that.hkvInfo.port,
        that.hkvInfo.username,
        that.hkvInfo.password,
        {
          async: false,
          success: (xmlDoc) => {
            //TODO 获取通道信息
            that.getChannelInfo();
            that.getDevicePort(that.hkvInfo.ip + "_" + that.hkvInfo.port);
            that.loginLoading = false;
            this.clickStartRealPlay();
          },
          error: function () {
            that.loginLoading = false;
            that.$message({
              showClose: true,
              message: "登录失败",
              type: "error",
            });
          },
        }
      );
    },
    // 退出
    onLogout() {
      this.videoData.forEach((element) => {
        var szDeviceIdentify = element.ip + "_" + element.port;
        var iRet = WebVideoCtrl.I_Logout(szDeviceIdentify);
        if (0 == iRet) {
          //   this.$message({
          //     showClose: true,
          //     message: "退出成功",
          //     type: "success",
          //   });
        } else {
          // this.$message({
          //   showClose: true,
          //   message: "退出失败",
          //   type: "error",
          // });
        }
      });
    },
    clickStartRealPlay() {
      console.log("开始预览", this.index);
      // 开始预览
      var that = this;
      that.startPlayLoading = true;
      var szDeviceIdentify = that.hkvInfo.ip + "_" + that.hkvInfo.port;
      that.startRealPlay(szDeviceIdentify, this.index, that.hkvInfo.channels[0]);
      that.startPlayLoading = false;
    },
    startRealPlay(szDeviceIdentify, iWndIndex, iChannelID) {
      var that = this;
      WebVideoCtrl.I_StartRealPlay(szDeviceIdentify, {
        iRtspPort: that.iRtspPort,
        iWndIndex: iWndIndex,
        iChannelID: iChannelID,
        bZeroChannel: that.bZeroChannel,
        success: function () {
          //   that.$notify({
          //     title: "成功",
          //     message: "开始预览通道" + iChannelID + "成功",
          //     type: "success",
          //   });
        },
        error(status, xmlDoc2) {
          console.log(xmlDoc2); //不能删除
          // that.$notify({
          //   title: "失败",
          //   message: "开始预览通道" + iChannelID + "失败",
          //   type: "error",
          // });
          if (status === 403) {
            console.log("szInfo 设备不支持Websocket取流!");
          } else {
            console.log("开始预览失败 ", status, xmlDoc2);
          }
        },
      });
    },
    videoInitPlugin() {
      this.$nextTick(() => {
        var iRet = WebVideoCtrl.I_CheckPluginInstall();
        if (iRet === -1) {
          // alert("您还未安装过插件,双击开发包目录里的WebComponentsKit.exe安装");
          this.myFunction();
          return;
        }
        this.initPlugin();
      });
    },
    myFunction() {
      var r = confirm("您还未安装过插件,请下载后查看摄像!");
      if (r == true) {
        window.location.href = "/WebComponentsKit.exe";
      } else {
      }
    },
    initPlugin() {
      WebVideoCtrl.I_InitPlugin("100%", "100%", {
        bWndFull: true, //是否支持单窗口双击全屏,默I_CheckPluginInstall
        iWndowType: this.iWndowType, //默认展示几个摄像头1x1 2x2
        cbInitPluginComplete: function () {
          WebVideoCtrl.I_InsertOBJECTPlugin("divPlugin");
          // 检查插件是否最新
          if (WebVideoCtrl.I_CheckPluginVersion() === -1) {
            return;
          }
        },
      });
      for (var i = 0; i < this.videoData.length; i++) {
        this.hkvInfo = this.videoData[i];
        this.index = i;
        this.onLogin();
      }
    },
    getDevicePort(szDeviceIdentify) {
      var oPort = WebVideoCtrl.I_GetDevicePort(szDeviceIdentify);
      this.iRtspPort = oPort.iRtspPort;
    },

    clickStopRealPlay: function () {
      for (var i = 0; i <= this.index; i++) {
        setTimeout(this.stopRealPlay(i), 1000);
      }
    },
    stopRealPlay: function (iWndIndex) {
      var that = this;
      WebVideoCtrl.I_Stop({
        iWndIndex: iWndIndex,
        success: function () {
          //   that.$notify({
          //     title: "成功",
          //     message: "停止预览窗口" + iWndIndex + "成功",
          //     type: "success",
          //   });
        },
        error: function () {
          // that.$notify({
          //   title: "失败",
          //   message: "停止预览窗口" + iWndIndex + "失败",
          //   type: "error",
          // });
        },
      });
    },
    // 获取通道,实际上可以根据自己的项目,获取数字通道,模拟通道,零通道中的一个或多个,不用全部获取(提高效率)
    getChannelInfo: function () {
      var that = this;
      var szDeviceIdentify = this.hkvInfo.ip + ":" + this.hkvInfo.port;
      // 数字通道
      that.hkvInfo.channels = [];
      WebVideoCtrl.I_GetDigitalChannelInfo(szDeviceIdentify, {
        async: false,
        mysuccess: function (xmlStr) {
          console.log("mysuccess I_GetDigitalChannelInfo: ", xmlStr);
          var jsonObj = that.$x2js.xml2js(xmlStr);
          var list = jsonObj.InputProxyChannelStatusList.InputProxyChannelStatus;
          for (var x = 0; x < list.length; x++) {
            that.hkvInfo.channels.push(list[x].id);
          }
        },
        success: function (xmlDoc) {},
        error: function (status, xmlDoc) {
          console.log("获取数字通道失败");
        },
      });
      // 模拟通道
      WebVideoCtrl.I_GetAnalogChannelInfo(szDeviceIdentify, {
        async: false,
        mysuccess: function (xmlStr) {
          var jsonObj = that.$x2js.xml2js(xmlStr);
          console.log("模拟通道mysuccess", xmlStr);
          var id = jsonObj.VideoInputChannelList.VideoInputChannel.id;
          that.hkvInfo.channels.push(id);
        },
        success: function (xmlStr) {
          console.log("模拟通道success", xmlStr);
        },
        error: function (status, xmlDoc) {
          console.log("模拟通道error", xmlDoc);
        },
      });
      // TODO 零通道
    },
  },
};
</script>
<style scoped>
.video_box {
  width: 100%;
  height: 100%;
}

.plugin {
  width: 100%;
  height: 100%;
}

.my-tag {
  margin-left: 3px;
}

.my-group-btn {
  margin-top: 5px;
}
</style>


 

  • 0
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

霸道流氓气质

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值