You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

297 lines
9.1 KiB

2 years ago
<template>
<div id="videoWrapper">
<canvas ref="videoCanvas" id="videoCanvas" :width="canvasWidth" :height="canvasHeight">
</canvas>
<video ref="videoPlayer" id="videoPlayer" autoplay muted
@loadedmetadata="changeVideoCanvasSize" @mouseover="mouseOverVideo" @mouseout="mouseOutVideo"
@mousedown="mouseDownVideo">
</video>
<div v-for="item in labelList" class="labels" :key="item.id" :style="`top:${canvasHeight*item.canvasTopRatio}px;left:${canvasWidth*item.canvasLeftRatio}px`">
<div class="labels-item" @click="test(item.id)">
<!-- <div class="labels-item" v-if="item.inFlag"> -->
<img src="@/assets/images/dialog.png" width="80" height="50" alt="">
<span>{{item.name}}</span>
</div>
</div>
</div>
</template>
<script setup lang='ts'>
////@ts-nocheck
import { ref, h, onMounted, getCurrentInstance, ComponentInternalInstance, onUnmounted,watch } from "vue";
import * as markLabelApi from '@/axios/cameraMark/markLabelApi';
import * as markSearchApi from '@/axios/core/markSearchApi';
import { useStore } from '@/store/index';
import { apiUrl } from "@/axios";
import {storeToRefs} from 'pinia';
import Msg from "@/utils/message";
const { proxy } = getCurrentInstance() as ComponentInternalInstance;
let piniaStore = useStore();
let player = <HTMLVideoElement>document.querySelector('#videoPlayer')
let canvas = <HTMLCanvasElement>document.querySelector('#videoCanvas')
let canvasWidth = ref(0)
let canvasHeight = ref(0)
let curSelectKey = storeToRefs(piniaStore).curSelectKey
let cameraMap = storeToRefs(piniaStore).cameraMap
let webRtcServer: any = ref()
let isActiveChoose = ref(false)
let labelList=ref<any[]>([])
onMounted(() => {
{
player = <HTMLVideoElement>document.querySelector('#videoPlayer');
canvas = <HTMLCanvasElement>document.querySelector('#videoCanvas');
// loadTreeData();
loadVideoPlayer();
loadVideoCanvas();
}
})
watch(curSelectKey,(newVal,oldVal)=>{
switchCamera(newVal)
})
function test(id:number){
console.log(id,"id++++++++++++");
markLabelApi.Delete({id}).then((res:any)=>{
console.log(res.data);
if(res.data.code==200){
let msg=res.data.data==true?"删除成功":"删除失败"
if(res.data.data){
labelList.value=labelList.value.filter((element:any) => {
return element.id!=id
});
Msg.success("删除成功")
return
}
}
Msg.error("删除失败")
})
}
function loadVideoPlayer() {
let elmId = 'videoPlayer';
let url = apiUrl.WebRtcUrl;
webRtcServer.value = new WebRtcStreamer(elmId, url);
}
function loadVideoCanvas() {
window.addEventListener('resize', () => {
changeVideoCanvasSize();
});
}
function changeVideoCanvasSize() {
canvasWidth.value = player.clientWidth;
canvasHeight.value = player.clientHeight;
}
function mouseOverVideo() {
// console.log("移入");
if (!isActiveChoose.value) return;
player.classList.add('activeChoose');
}
function mouseOutVideo() {
// console.log("移除");
if (!isActiveChoose) return;
player.classList.remove('activeChoose');
}
function mouseDownVideo(e: MouseEvent) {
if (!isActiveChoose.value) return;
let cameraId = cameraMap.value.get(curSelectKey.value).id;
let name = 'markLabel-' + Date.now();
let videoWidth = player.videoWidth | 1920;
let videoHeight = player.videoHeight | 1080;
let canvasWidth = player.clientWidth;
let canvasHeight = player.clientHeight;
let canvasLeft = e.offsetX;
let canvasTop = e.offsetY;
let canvasLeftRatio = canvasLeft / canvasWidth;
let canvasTopRatio = canvasTop / canvasHeight;
let entity = {
CbCameraId: cameraId,
Name: name,
VideoWidth: videoWidth,
VideoHeight: videoHeight,
CanvasLeftRatio: canvasLeftRatio,
CanvasTopRatio: canvasTopRatio
}
console.log(entity);
markLabelApi.AddReturnId({
'entity': entity
}).then((res: any) => {
let markLabelId: number = res.data.data;
console.log(markLabelId);
if (markLabelId <= 0) return;
markSearchApi.ActivateMarkLabel({
'cameraId': cameraId,
'markLabelId': markLabelId
}).then((res: any) => {
let ret: boolean = res.data.data;
});
})
}
function activateChoose() {
if (curSelectKey.value.length == 0) return;
isActiveChoose.value = true;
}
function deactivateChoose() {
if (curSelectKey.value.length == 0) return;
isActiveChoose.value = false;
}
function switchCamera(cameraId: string) {
console.log('camera switch.');
// step1, get camera obj.
console.log('get camera obj.');
let cameraObj = cameraMap.value.get(cameraId);
if (!cameraObj) {
console.log('camera obj not found.');
return;
}
// object to proxy, ?
console.log(cameraObj, '111111');
// step2, get camera rtsp url.
console.log('get camera rtsp url.');
let rtspUrl = getRtspUrl(cameraObj);
// step3, connect webrtc-steamer.
console.log('connect webrtc-steamer.');
webRtcServer.value.disconnect();
webRtcServer.value.connect(rtspUrl);
// step4, active camera searcher.
markSearchApi.IsExistsSearcher({
'cameraId': cameraObj.id
}).then((res: any) => {
let flag: boolean = res.data.data;
if (!flag) {
console.log('not exist searcher.');
markSearchApi.ActiveSearcher({
'cameraId': cameraObj.id
}).then((res: any) => {
let flag: boolean = res.data.data;
console.log('activate searcher : ', flag);
if (flag) {
console.log('load camera labels');
getLabel(cameraObj.id)
loadMarkLabelsByLoop(cameraObj);
}
});
} else {
console.log('load camera labels');
getLabel(cameraObj.id)
loadMarkLabelsByLoop(cameraObj);
}
})
// step5, load camera labels.
}
function getRtspUrl(cameraObj: any): string {
// 模拟 onvif
return "rtsp://admin:hk123456@192.168.1.65:554/Streaming/Channels/101?transportmode=unicast&profile=Profile_1";
}
function getLabel(cbCameraId:string|number){
markLabelApi.GetList({cbCameraId}).then((res:any)=>{
if(res.data.code==200){
console.log(res,'res');
labelList.value=res.data.data
}
})
}
function loadMarkLabelsByLoop(cameraObj: any, ms: number = 1000) {
if (curSelectKey.value !== cameraObj.id) {
console.log('load camera labels end.');
return;
}
loadMarkLabels(cameraObj);
setTimeout(() => {
loadMarkLabelsByLoop(cameraObj, ms);
}, ms);
}
function loadMarkLabels(cameraObj: any) {
markSearchApi.GetMarkLabelCalcResultList({
'cameraId': cameraObj.id
}).then((res: any) => {
let list: Array<any> = res.data.data;
list.forEach((element:any) => {
labelList.value.forEach((item:any,index:number) => {
if(element.id==item.id){
labelList.value[index].canvasLeftRatio=element.canvasLeftRatio
labelList.value[index].canvasTopRatio=element.canvasTopRatio
labelList.value[index].inFlag=element.inFlag
}
});
});
// console.log(labelList);
// drawMarkLabels(list);
});
}
function drawMarkLabels(markLabels: Array<any>) {
let ctx = canvas.getContext('2d');
if (!ctx) return;
ctx.clearRect(0, 0, canvasWidth.value, canvasHeight.value);
for (let markLabel of markLabels) {
if (!markLabel.inFlag) continue;
let x = Math.round(canvasWidth.value * markLabel.canvasLeftRatio);
let y = Math.round(canvasHeight.value * markLabel.canvasTopRatio);
x = canvasWidth.value * markLabel.canvasLeftRatio;
y = canvasHeight.value * markLabel.canvasTopRatio;
// console.log(markLabel);
ctx.beginPath();
ctx.arc(x, y, 5, 0, 2 * Math.PI);
ctx.fillStyle = "red";
ctx.fill();
ctx.closePath();
}
}
onUnmounted(() => {
{
console.log('beforeUnmount.');
// 释放 webRtcServer
if (!webRtcServer.value) return;
console.log(123);
webRtcServer.value.disconnect();
webRtcServer.value = null;
}
})
</script>
<style scoped lang='less'>
#videoWrapper {
height: 100vh;
position: relative;
overflow: hidden;
#videoCanvas {
position: absolute;
}
#videoPlayer {
height: 100%;
width: 100%;
object-fit: fill;
}
.labels{
position: absolute;
top: 0;
left: 0;
transform: translate(-50%,-50%);
z-index: 2;
.labels-item{
position: relative;
span{
position: absolute;
top: 50%;
left: 50%;
transform: translate(-50%,-50%);
}
}
}
}
</style>