使用VUE+Element + webSocket +videojs + HLS 直播功能
祝点赞收藏转发的小伙伴 原神 2.2 胡桃公子必不歪 。:.゚ヽ(。???。)ノ゚.:。+゚
先说方法 (因为我是两个demo,所以就分开写了,不过大体的逻辑一样,复制粘贴改改就行)
方法1:
使用websocket连接后端返回返回直播流,然后前端使用videojs接收(会有延迟)
方法2:
使用websoclet连接后端返回一张一张的图片,然后不停换图片以达到视频的效果(不会有延迟)
效果图 1 对应方法1的 视频展示方法
效果图2,对应方法2的 图片展示方法
重难点分析
方法一:使用websocket连接后端返回返回直播流(我的是hls流 然后hls还分H.265和H.264,这个视频方法只支持H.264的,H.265请用图片方式),然后前端使用videojs接收
重点:安装插件
package.json添加插件
{"video.js": "^7.11.8","videojs-contrib-hls": "^5.15.0",}
然后项目重新npm i main.js 添加
// video 组件
import Videojs from 'video.js'
import 'video.js/dist/video-js.css'
Vue.prototype.$video = Videojs
import hls from 'videojs-contrib-hls';
Vue.use(hls); // 要播放hls流, 这哥们就要上场
难点分析
难点1. 分屏功能(一般是1屏,4屏,9屏)
难点2. websocket的循环创建以及关闭的时候的销毁
难点3. videojs的销毁和初始化:
为什么一定要销毁video.js呢?这个销毁不是指你vue页面的destroyed,即使你关闭了页面,websocket断掉,但是他这个videojs还会继续解析地址,并不会销毁,所以会出现大量的报错,2分钟不管,或者你切换到别的页面后,用一会,浏览器就崩溃了。然后就是当你销毁掉,再打开这个页面的时候,如何重新创建和重新初始化,你总不可能逼着用户,每次切换这个页面的时候让强制他重新刷浏览器吧?不会吧?不会吧?
难点4:选择不同摄像头(就是那个树形菜单,有的点了之后是一屏,有的点了之后是展开,有的点了之后是多屏),以及点击某个摄像头调整他的视角和直播的联动(点击摄像头调整位置这个简单)
难点5 :所有东西联动
这个比较难,因为他涉及到了初始化页面;数据重新渲染顺序;初始化直播;然后树形菜单的默认选中;然后请求到数据显示直播后,再点击分屏或者摄像头切换的时候videojs的销毁和video的创建和初始化等
方法二:使用websoclet连接后端返回一张一张的图片,然后不停换图片以达到视频的效果(话说视频的原理不就是一帧一帧的穿起来的吗?)
重难点分析
重点:没什么重点吧…他就是个拿值然后赋值的过程也用不到销毁video什么的
难点:当你多个websoclet拿到值后,要循环渲染到页面上
因为你img是循环出来的,并不是双向绑定,所以你会发现不管怎么绑,他都是只有一张图片,并不会切换图片,所以要用到 this.$set 来强行赋值
方法一
上代码,复制出来研究吧,在这看不明白,每个函数都有注释
<!--树形菜单 具体属性翻element官网即可-->
<el-tree
:current-node-key="defaultChecked"
:default-expanded-keys="defaultExpanded"
node-key="id"
:highlight-current="true"
ref="tree"
:data="treeData"
:props="defaultProps"
accordion
@node-click="handleNodeClick"
:filter-node-method="filterNode"
></el-tree>
<!--云台 这里到没什么,简单的请求接口-->
<div v-if="ISholder" class="pa yuntai" :style="{height: rightScrollHeight}">
<div @click="yuntaiOpen()" class="yuntai-title">{{siteName}}</div>
<div>
<div class="yuntai-ctl-box">
<div class="yuntai-ctl-direction">
<div class="yuntai-ctl-direction-item">
<img @click="handlPtz(25)" src="~@/assets/img/RealVideo/zuoshang.png" alt="">
<img @click="handlPtz(21)" src="~@/assets/img/RealVideo/shang.png" alt="">
<img @click="handlPtz(26)" src="~@/assets/img/RealVideo/youshang.png" alt="">
<img @click="handlPtz(23)" src="~@/assets/img/RealVideo/zuo.png" alt="">
<img src="~@/assets/img/RealVideo/shuaxin.png" alt="">
<img @click="handlPtz(24)" src="~@/assets/img/RealVideo/you.png" alt="">
<img @click="handlPtz(27)" src="~@/assets/img/RealVideo/youxi.png" alt="">
<img @click="handlPtz(22)" src="~@/assets/img/RealVideo/xia.png" alt="">
<img @click="handlPtz(28)" src="~@/assets/img/RealVideo/youx.png" alt="">
</div>
</div>
<div class="yuntai-ctl-other">
<div>
<img width="40px" style="margin: 5px;cursor: pointer;" @click="handlPtz(13)" src="~@/assets/img/RealVideo/jia.png" alt="">
<span style="margin:0 10px;">缩放</span>
<img width="40px" style="margin: 5px;cursor: pointer;" @click="handlPtz(14)" src="~@/assets/img/RealVideo/jian.png" alt="">
</div>
<div>
<img width="40px" style="margin: 5px;cursor: pointer;" @click="handlPtz(11)" src="~@/assets/img/RealVideo/jia.png" alt="">
<span style="margin:0 10px;">聚焦</span>
<img width="40px" style="margin: 5px;cursor: pointer;" @click="handlPtz(12)" src="~@/assets/img/RealVideo/jian.png" alt="">
</div>
<div>
<img width="40px" style="margin: 5px;cursor: pointer;" @click="handlPtz(23)" src="~@/assets/img/RealVideo/xuanzhuan.png" alt="">
<span style="margin:0 10px;">旋转</span>
<img width="40px" style="margin: 5px;cursor: pointer;" @click="handlPtz(24)" src="~@/assets/img/RealVideo/xuanzhuan1.png" alt="">
</div>
</div>
</div>
<div class="yuntai-speed">
<div class="yuntai-speed-speed" ><span>云台速度</span> </div>
<div class="yuntai-speed-silder" >
<el-slider :max="7" @change="handleYunKongZhi()" v-model="yuntaiSpeed"></el-slider>
</div>
</div>
<div class=yuntai-repect>
<el-button class="yuntai-button blue" type="">复位</el-button>
</div>
</div>
</div>
<!--视频 这里重点说一下-->
<div class="center h100per">
<div class="center-top">
<div class="flex-wrap">
<div class="videoContainer" >
<el-row style="margin:0" class="video-box" :gutter="20">
<!--videoNum 这个就是代表了你页面有多少个视频在播放-->
<el-col class="borders" :class="currentIndex === index ?'active':''" v-for="(item,index) in videoNum" :key="item.id" :span="videoctl">
<!--height 高是动态的 --->
<div :style="{height:screenHeight}" :id='"myidFather"+index' class="temp-bg">
<div class="video-name"> {{item.name}} </div>
<!--
click 点击事件
play 播放事件(点击事件和播放事件不一样,别混)
style 他的高也是动态的
poster 封面图
id 要给id,要不然你初始化的时候没发初始化
--->
<video
@click="getVideos(item,index)"
@play="handleInitLive(index)"
:style="{height:screenHeight}"
style="width:100%"
:poster="item.url"
:id='"myid"+index'
class="video-js vjs-default-skin vjs-big-play-centered"
controls
preload="auto">
<!--这里就不用说了吧 --->
<source :ref='"previewSource"+index' type="application/x-mpegURL" :src="item.previewUrl">
</video>
</div>
</el-col>
</el-row>
<div class="screen-ctl">
<div v-if="ISholder" style="float:left;margin-left:20px">
<div class="YUbutton blue" v-if="recording" @click="record" > <img src="~@/assets/img/RealVideo/luxiang.png" alt=""> 录像 </div>
<div class="YUbutton blue" style="text-align:center" v-if="!recording" @click="recordStop" > 停止录像 </div>
<div class="YUbutton blue" @click="printscreen"> <img style="width:20px;" src="~@/assets/img/RealVideo/jietu.png" alt=""> 截图 </div>
</div>
<div v-else style="float:left;margin-left:20px">
<div class="YUbutton"> <img src="~@/assets/img/RealVideo/luxiang.png" alt=""> 录像 </div>
<div class="YUbutton"> <img style="width:20px;" src="~@/assets/img/RealVideo/jietu.png" alt=""> 截图 </div>
</div>
<div v-if="ISscreen" class="screenBtn" style="">
<div @click="handlChangeScreen(1)"></div><!--1屏-->
<i @click="handlChangeScreen(4)" class="el-icon-menu"></i><!--4屏-->
<i @click="handlChangeScreen(9)" class="el-icon-s-grid"></i><!--9屏-->
</div>
</div>
</div>
</div>
</div>
</div>
import 'videojs-contrib-hls'
import Cookies from 'js-cookie'
data(){
return {
player:'',//播放器
myPlayer:'',//选中的分屏
selectId:'',//云台速度
yuntaiSpeed:0,//树形菜单默认选中
defaultChecked:'',//默认展开
defaultExpanded:[],//分配控制
screenCtl:4,//分屏默认展示4个
videoNum:[ //默认给4个空的
{
id:1,
},
{
id:2,
},
{
id:3,
},
{
id:4,
}
],
videoctl:12,//el-col 的占比
screenHeight: '359px',//动态高度高
noneHeight:'23%',// 动态高度
filterText:'',//树形菜单过滤
treeData:[],// isImgVideo:true,
defaultProps: {//树形菜单选项转化
children: 'children',
label: 'name'
},
rightScrollHeight: '55px',//云台高度
player: undefined,//播放器 我这里设置的是undefined,因为在下面我要判断他是否创建过了,不要问我为什么不用空串 ‘’ 因为不行
isyuntai:false, //云台
websocket: [],//websocket数组
siteIdScreen:'',//传给后端的分屏量
cameraArr:[],//保存的摄像头数组
siteIdIndex:'', //保存的直播下标
currentIndex:'',//视频选中索引
ISholder:false,//是否展示云台控件和录像截图控件
ISscreen:true,//是否展示分屏控件
recording:true,//是否开始录像
siteName:'',//摄像机名称
siteId:'',//摄像机id
websocketPush:''//websocket一个的时候
}
},
//这个就不用说了吧,element自带的,抄一下就行
watch:{
//树形菜单搜索
defaultChecked(id){
// Tree 内部使用了 Node 类型的对象来包装用户传入的数据,用来保存目前节点的状态。可以用 $refs 获取 Tree 实例
this.$nextTick(() => {
if (id) {
this.$refs["tree"].setCurrentKey(id);
} else {
this.$refs["tree"].setCurrentKey(null);
}
})
},
//树形菜单搜索
filterText(val) {
this.$refs.tree.filter(val);
}
},
mounted(){
//加载树形菜单列表
this.fetchRealTimeData();
},
created:function(){
this.$nextTick(() => {
//初始化直播video
this.handleInitLive()
})
},
methods:{
//树形菜单搜索
filterNode(value, data) {
if (!value) return true;
return data.name.indexOf(value) !== -1;
},
//树形菜单列表
fetchRealTimeData(){
// 这里请求接口拿到数据
this.treeData = res.data;
if (this.treeData[0]) {
if (this.treeData[0].children.length !==0) {
//赋值一大堆默认值
this.defaultExpanded = [this.treeData[0].id]
this.selectId = this.treeData[0].children[0].id
this.defaultChecked = this.treeData[0].children[0].id
this.handleInitLive()//先初始化直播
var temp = this.treeData[0].children[0].children
for (let i = 0; i < temp.length; i++) {
this.cameraArr.push(temp[i].id)
}
this.getSiteListLevleTwo(4)
}
}
},
//树形菜单点击事件
//level 是element自带的
handleNodeClick(data, node) {
if(node.level !== 1){ //一级
this.selectId = data.id
}
if(node.level == 2){ //二级,
this.ISholder = false
this.ISscreen = true
this.cameraArr = []
for (let i = 0; i < data.children.length; i++) {
this.cameraArr.push(data.children[i].id)
}
this.getSiteListLevleTwo(4)//因为这里默认是多个视频,所以默认分4屏
this.handlChangeScreenTree(4)
}
if(node.level == 3){ //三级
for (let i = 0; i < this.websocket.length; i++) {
this.websocket[i].close()
}
//如果有视频播放,先干掉,然后再初始化
if (typeof (this.player) != "undefined") {
this.player.dispose() //销毁
this.player = undefined
this.videoNum = []
}
this.websocket = []
this.videoNum = []
this.ISholder = true
this.ISscreen = false
this.siteId = data.id
this.siteName = data.name
//然后走这个函数,把data传过去
this.getSiteListLevleFore(data.id)
}
},
//树形菜单点击第三级
getSiteListLevleFore(index){
this.$message('远程数据加载中,请稍后')
this.handlChangeScreenTree(index)
//请求数据
this.$http.get('/video/hikdevice/capturePics?ids='+index+'&limit=1').then(({ data: res }) => {
if (res.code !== 0) {
return this.$message.error(res.msg)
}
this.videoNum = res.data
this.videoNum[0].previewUrl = ''
this.siteIdIndex = 0
this.$nextTick(() => {
this.createWebSocket();//连websocket
})
this.handlChangeScreenTree(1)//,因为三级菜单这里只有一个视频,所以只分一屏即可
}).catch(() => {})
},
//树形菜单点击,以及补全分屏函数
getSiteListLevleTwo(index){
this.$message('远程数据加载中,请稍后')
this.handlChangeScreenTree(index)
this.$http.get('/video/hikdevice/capturePics?ids='+ this.cameraArr.join()+'&limit='+index ).then(({ data: res }) => {
if (res.code !== 0) {
return this.$message.error(res.msg)
}
if (res.code !== 0) {
var arr = []
var temp = 1
for (let i = 0; i < index; i++) {
let obj = {
id: temp ++
}
arr.push(obj)
}
this.videoNum = arr
return this.$message.error(res.msg)
}else{
this.videoNum = res.data;
//补全videoNum
if (this.videoNum.length !==0) {
if (index == 1) {
this.videoNum = res.data;
}
if (index == 4) {
for (let i = 0; i <= 4; i++) {
if (this.videoNum.length<4) {
var obj = {
id:i++
}
this.videoNum.push(obj)
}
}
}
if (index == 9) {
for (let i = 0; i <= 9; i++) {
let temp = 0
if (this.videoNum.length<9) {
var obj = {
id:temp++
}
this.videoNum.push(obj)
}
}
}
}
else{
var arr = []
var temp = 1
for (let i = 0; i < index; i++) {
let obj = {
id: temp ++
}
arr.push(obj)
}
this.videoNum = arr
}
for (let i = 0; i < this.videoNum.length; i++) {
this.videoNum[i].previewUrl = ''
}
}
}).catch(() => {})
},
//视频播放
getVideos(item,index){
console.log(this.recording);
//多个播放版本
if (this.ISholder) {
if (!this.recording) {
this.$message.warning('请停止录像后操作')
return false
}
}
if (item.name) {
var arr = []
for (let i = 0; i < this.websocket.length; i++) {
arr.push(this.websocket[i].siteId)
}
if (arr.indexOf(item.id)>-1) {
this.currentIndex = index
this.siteId = item.id
this.siteName = item.name
this.siteIdIndex = index
}else{
this.currentIndex = index
this.siteId = item.id
this.siteName = item.name
this.siteIdIndex = index
this.createWebSocket();
}
}else{
this.ISholder = false
this.currentIndex = index
}
},
//工具函数,找元素
filePush1(item){
let that=this
let refs=that.$refs
for(let key in refs){
return refs[item]
//这里遍历循环所有的 refs值 就可以拿到动态拼接$refs所要的对应值 这的item 是动态传的值
}
},
//开始创建WebSocket
createWebSocket(){
try {
//尝试连接
this.websocketPush = new WebSocket(`${window.SITE_CONFIG['VideoPreviewSocketURL']}?token=${Cookies.get('token')}`)
this.initWebSocket();
} catch (e) {
console.log(e);
}
},
// 初始化weosocket
initWebSocket() {
this.websocketPush.onopen = this.websocketonopen;
this.websocketPush.onerror = this.websocketonerror;
this.websocketPush.onmessage = this.websocketonmessage;
this.websocketPush.onclose = this.websocketclose;
},
//连接成功提示字样
websocketonopen() {
console.log('连接成功');
this.websocketPush.siteId = this.siteId
this.websocket.push(this.websocketPush)
this.websocketsend(this.siteId)
},
//连接错误
websocketonerror(e) {
console.log(e);
},
//数据接收
websocketonmessage(e) {
if (res.code == '0') {
this.$message.success(res.data)
}
if(res.code == 1){
this.downLoad(res.data)
}
if (res.code == 3) {
this.ISholder = true
this.$message.success('直播初始化完毕')
this.videoNum[this.siteIdIndex].previewUrl=res.data
this.$nextTick(() => {
this.filePush1('previewSource'+this.siteIdIndex)[0].src = res.data
this.handleInitLive(this.siteIdIndex)
})
}
if (res.code == 500) {
this.$message.warning('服务器正忙,请重试')
}
},
//数据发送
websocketsend(item){
for (let i = 0; i < this.websocket.length; i++) {
if (this.websocket[i].siteId == item) {
var obj={id:item,record:3}
this.websocket[i].send(JSON.stringify(obj))
}else{
}
}
},
//服务关闭
websocketclose(e) {
console.log("connection closed ");
},
//真正的关闭
websocketcloses(){
this.websocket.close()
},
//点击分屏请求接口
hanldfetchDevicePage(index){
for (let i = 0; i < this.websocket.length; i++) {
this.websocket[i].close()
}
this.websocket = []
this.siteIdScreen = index
this.getSiteListLevleTwo(index)
},
//分屏点击事件
handlChangeScreen(item){
switch (item) {
case 1:
this.screenCtl = 1
this.videoctl = 24
this.screenHeight = '720px'
this.noneHeight = '24%'
this.hanldfetchDevicePage(this.screenCtl)
break;
case 4:
this.screenCtl = 4
this.videoctl = 12
this.screenHeight = '359px'
this.noneHeight = '23%'
this.hanldfetchDevicePage(this.screenCtl)
break;
case 9:
this.screenCtl = 9
this.videoctl = 8
this.screenHeight = '238px'
this.noneHeight = '20%'
this.hanldfetchDevicePage(this.screenCtl)
break;
default:
this.screenCtl = 4
this.videoctl = 12
this.screenHeight = '359px'
this.noneHeight = '23%'
this.hanldfetchDevicePage(this.screenCtl)
}
},
//分屏事件(不请求接口)
handlChangeScreenTree(item){
switch (item) {
case 1:
this.screenCtl = 1
this.videoctl = 24
this.screenHeight = '720px'
this.noneHeight = '24%'
// this.selectId
break;
case 4:
this.screenCtl = 4
this.videoctl = 12
this.screenHeight = '359px'
this.noneHeight = '23%'
break;
case 9:
this.screenCtl = 9
this.videoctl = 8
this.screenHeight = '238px'
this.noneHeight = '20%'
break;
default:
this.screenCtl = 4
this.videoctl = 12
this.screenHeight = '359px'
this.noneHeight = '23%'
}
},
//初始化直播列表
handleInitLive(index){
for (let i = 0; i < this.videoNum.length; i++) {
if (this.videoNum[i].name) {
this.$nextTick(() => {
setTimeout(() => {
this.player = this.$video(document.getElementById('myid'+index+''), {
controls: true,
autoplay: false,
preload: 'auto',
controlBar:{
playToggle:true
}
})
}, 500);
})
}
}
},
//页面销毁
destroyed: () =>{
this.player.dispose(); //销毁
this.$video.dispose();
},
//云台方向控制
handlPtz(cmd){
var obj = {
id:this.siteId,
command:cmd
}
this.$http.post('/video/hikdevice/ptzControl', obj).then(({ data: res }) => {
if (res.code !== 0) {
return this.$message.error(res.msg)
}
}).catch(() => {})
},
//调节云台速度
handleLiveWebSocket(){
var obj = {
id:this.siteId,
speed:this.yuntaiSpeed
}
this.$http.post('/video/hikdevice/ptzControl', obj).then(({ data: res }) => {
if (res.code !== 0) {
return this.$message.error(res.msg)
}
}).catch(() => {})
},
//停止录像
recordStop(){
this.recording = true
let actions = {id:this.siteId,record:0};
for (let i = 0; i < this.websocket.length; i++) {
if (this.websocket[i].siteId == this.siteId) {
this.websocket[i].send(JSON.stringify(actions));
}
}
},
//截屏
printscreen(){
this.$http.get('video/hikdevice/capturePic?id='+this.siteId+'&name='+this.siteName).then(({ data: res }) => {
var obj={
id:this.siteId,
name:this.siteName
}
var params = qs.stringify({
'token': Cookies.get('token'),
...obj
})
window.location.href = `${window.SITE_CONFIG['apiURL']}/video/hikdevice/capturePic?${params}`
}).catch(() => {})
},
}
方法二
大致和上面一样,就是接收数据和页面展示方式不太一样,然后你需要创建两个部分websocket,一部分是只有一张图片的时候,另一部分是多个websocket的时候,然后把销毁函数什么的删了就行了
<el-tree
:current-node-key="defaultChecked"
ref="tree"
class="filter-tree"
default-expand-all
node-key="id"
:filter-node-method="filterNode"
:data="data"
:props="defaultProps"
@node-click="handleNodeClick"
></el-tree>
<div class="flex-wrap">
<div class="videoContainer" v-if="!isOne">
<!-- 多个 -->
<div class="videoContainer-box" style="overflow:auto;">
<div class="videoContainer-item" style="float:left" v-for="(item,index) in videoData" v-bind:key="item.id">
<div
v-loading="loading[index]"
element-loading-text="视频加载中"
element-loading-spinner="el-icon-loading"
element-loading-background="rgba(0, 0, 0, 0.8)"
style="width:600px;height:360px;margin:20px;">
<img style="width:100%" :src="videoData[index].src" alt="">
</div>
</div>
</div>
<div style="text-align:center">
<el-pagination
@size-change="handleSizeChange"
@current-change="handleCurrentChange"
:current-page="pageNum"
:page-size="pageSize"
layout="total, prev, pager, next"
:total="total">
</el-pagination>
</div>
</div>
<div class="videoContainer-one" v-if="isOne">
<!-- 一个 -->
<div class="videoContainer-box" style="overflow:auto;">
<!-- <div v-else> 加载中 </div> -->
<div
v-loading="loadingOne"
element-loading-text="视频加载中"
element-loading-spinner="el-icon-loading"
element-loading-background="rgba(0, 0, 0, 0.8)"
style="width:97%;height:825px;margin:20px;">
<img style="width:100%;" :src="ImgSrc" alt="">
</div>
</div>
</div>
</div>
data(){
return {
loadingOne:true,
loading:[
true,
true,
true,
true,
],
ImgSrc:'',
websocket: null,
websocketArr:[], //wensocket数组合集地址
isOne:false, //判断多个视频还是一个视频
data: [],
pageNum:1,//当前页
total:0,//总条数
pageSize:4,
//树形菜单默认选中
defaultChecked:'',
middleData:[], //中间件
oneSrc:'', //一个视频播放的时候的地址
videoData:[],
//默认展开
defaultExpanded:[],
//树形菜单过滤
filterText:'',
//树形菜单选项转化
defaultProps: {
children: 'children',
label: 'name'
},
tempVideoArr:[]
}
},
mounted() {
// this.createWebSocket(0)
videoTree().then(response => {
//老规矩,还是从树形菜单下手
console.log(response);
this.data = response.data
this.defaultChecked = this.data[0].id
this.middleData = this.data[0].children || 0
var lengths = this.middleData.length
this.total = lengths
this.demoData();
});
},
methods:{
demoData(){
if (this.middleData.length>4) {
this.videoData = this.returnArea(this.middleData,0)
this.FORE_VIDEO_WEBSOCKET()
}
},
//一个视频的时候
ONE_VIDEO_WEBSOCKET(data){
this.createWebSocketOne(data)
},
//多个视频的时候
FORE_VIDEO_WEBSOCKET(){
for (let i = 0; i < this.videoData.length; i++) {
if (this.videoData[i].id) {
this.createWebSocket(i,this.videoData[i])
}else{
}
}
},
//一个视频关闭连接
ONE_CLOSE_WEBSOCKET(){
this.websocket.close()
this.websocket = null
},
//多个视频关闭连接
FORE_CLOSE_WEBSOCKET(isgo){
console.log(this.websocketArr);
for (let i = 0; i <= this.websocketArr.length; i++) {
if (this.websocketArr[i]) {
console.log('断');
this.websocketArr[i].close();
}
}
console.log(this.websocketArr);
this.websocketArr = []
this.videoData = []
if (isgo) {
this.pageNum = this.pageNum
this.returnArea(this.middleData,this.pageNum)
}
},
handleSizeChange(val) {
console.log(`每页 ${val} 条`);
},
handleCurrentChange(val) {
console.log(val);
this.pageNum = val
this.FORE_CLOSE_WEBSOCKET(true)
// console.log(`当前页: ${val}`);
},
//树形菜单搜索
filterNode(value, data) {
if (!value) return true;
return data.name.indexOf(value) !== -1;
},
//0-4 1
//4-8 2
//8-12 3
returnArea(tempVideoArr,one){
console.log(tempVideoArr);
console.log(one);
if (one == 0) {
return tempVideoArr.slice(0,4)
}else{
console.log(999);
// console.log((one-1)*4);
// console.log(one*4);
// console.log(tempVideoArr.slice( ((one-1)*4), one*4));
// return tempVideoArr.slice( ((one-1)*4), one*4)
this.polishing(tempVideoArr.slice(((one-1)*4), one*4))
}
},
polishing(data){
console.log(data);
console.log(777);
for (let i = 0; i < data.length; i++) {
if (data.length <4) {
data.push({})
}
}
this.videoData = data
this.FORE_VIDEO_WEBSOCKET()
},
handleNodeClick(data,v) {
if (v.level == 1) {
if (this.videoData.length>0) {
this.FORE_CLOSE_WEBSOCKET()
this.ONE_CLOSE_WEBSOCKET()
this.ImgSrc = ''
this.videoData = []
this.isOne = false
console.log(data);
this.middleData = data.children
if (this.middleData.length>4) {
//开启连接
console.log(this.returnArea(this.middleData,0));
this.videoData = this.returnArea(this.middleData,0)
console.log(this.videoData);
this.FORE_VIDEO_WEBSOCKET()
}else{
console.log(777);
}
}else{
this.ImgSrc = ''
this.videoData = []
this.isOne = false
console.log(data);
this.middleData = data.children
if (this.middleData.length>4) {
//开启连接
console.log(this.returnArea(this.middleData,0));
this.videoData = this.returnArea(this.middleData,0)
console.log(this.videoData);
this.FORE_VIDEO_WEBSOCKET()
}else{
console.log(777);
}
}
}else{
// this.ONE_VIDEO_WEBSOCKET(data)
console.log(this.websocket);
if (this.websocket) {
//多个关闭
this.ONE_CLOSE_WEBSOCKET()
this.videoData = []
this.isOne = true
this.ImgSrc = ''
this.ONE_VIDEO_WEBSOCKET(data)
}else{
//多个关闭
this.FORE_CLOSE_WEBSOCKET()
this.ONE_VIDEO_WEBSOCKET(data)
this.videoData = []
this.pageNum = 1
this.isOne = true
}
}
},
//第一部分WebSocket
createWebSocketOne(data){
this.$message('远程数据连接中,请稍后')
try {
//尝试连接
this.websocket = new WebSocket('ws://172.16.99.2:8091/company/supervision/websocket/video/preview?Authorization='+this.$store.state.user.token)
this.initWebSocketOne(data);
} catch (e) {
console.log(e);
}
},
// 初始化weosocket
initWebSocketOne(data) {
var that = this
this.websocket.onopen = function(){
// console.log();
// console.log(data);
console.log('连接成功');
//数据发送
that.websocketsendOne(data)
}
this.websocket.onerror = this.websocketonerrorOne;
this.websocket.onmessage = function(e){
// console.log(e.data);
// console.log(JSON.parse(e.data));
var json = JSON.parse(e.data)
if (json.code ==500) {
that.loadingOne = true
that.ImgSrc = ""
}else{
that.loadingOne = false
that.ImgSrc = "data:" +';base64,'+json.data
}
};
this.websocket.onclose = this.websocketcloseOne;
},
//连接错误
websocketonerrorOne(e) {
console.log(e);
},
//数据发送
websocketsendOne(data){
var tempObj = {
id: data.id,
}
console.log(tempObj);
this.websocket.send(JSON.stringify(tempObj));
},
//服务关闭
websocketcloseOne(e) {
console.log("connection closed ");
},
//真正的关闭
websocketclosesOne(){
this.websocket.close()
},
//第二部分WebSocket
createWebSocket(wsobj,data){
this.$message('远程数据连接中,请稍后')
try {
//尝试连接
this.websocketArr[wsobj] = new WebSocket('ws://172.16.99.2:8091/company/supervision/websocket/video/preview?Authorization='+this.$store.state.user.token)
this.initWebSocket(wsobj,data);
} catch (e) {
console.log(e);
}
},
// 初始化weosocket
initWebSocket(wsobj,data) {
var that = this
this.websocketArr[wsobj].onopen = function(){
// console.log(wsobj);
// console.log(data);
console.log('连接成功');
//数据发送
that.websocketsend(wsobj,data)
}
this.websocketArr[wsobj].onerror = this.websocketonerror;
this.websocketArr[wsobj].onmessage = function(e){
// console.log(e.data);
// console.log(JSON.parse(e.data));
var json = JSON.parse(e.data)
// console.log(json);
if (json.code ==500) {
that.loading[wsobj] = true
var tempObj = {
...that.videoData[wsobj],
src: ""
}
that.$set(that.videoData,wsobj,tempObj);
}else{
that.loading[wsobj] = false
var tempObj = {
...that.videoData[wsobj],
src: "data:" +';base64,'+json.data
}
that.$set(that.videoData,wsobj,tempObj);
// that.oneImg = "data:" +';base64,'+e.data
}
};
this.websocketArr[wsobj].onclose = this.websocketclose;
console.log(this.websocketArr);
},
//连接成功提示字样
websocketonopen(wsobj,data) {
},
//连接错误
websocketonerror(e) {
console.log(e);
},
//数据发送
websocketsend(wsobj,data){
// console.log(wsobj);
// console.log(data);
var tempObj = {
id: data.id,
}
console.log(tempObj);
this.websocketArr[wsobj].send(JSON.stringify(tempObj));
// console.log(this.websocketArr);
},
//服务关闭
websocketclose(e) {
console.log("connection closed ");
},
//真正的关闭
websocketcloses(){
this.websocketArr[wsobj].close()
},
},
destroyed(){
this.FORE_CLOSE_WEBSOCKET()
this.ONE_CLOSE_WEBSOCKET()
this.videoData = []
this.ImgSrc = ''
},
OK,大致就是这样了,因为我这个是两个demo,视频的一个,图片的一个
总结
其实写完就会发现,没什么难的,把逻辑梳理清楚,其他的就是时间问题,喜欢的话点赞收藏转发支持一下~
|