Fuyuu
1 year ago
14 changed files with 320 additions and 31 deletions
@ -0,0 +1,283 @@ |
|||||
|
<!-- |
||||
|
测试页面 |
||||
|
|
||||
|
目录位置:无 |
||||
|
功能概述:用于测试2d数据标注插件canvas-select的相关功能,包括基础图形绘制.编辑,数据保存.回显 |
||||
|
同时结合rtsp视频播放功能,完成基于视频资源的图形标注 |
||||
|
--> |
||||
|
<template> |
||||
|
<div class="box"> |
||||
|
<div class="left"> |
||||
|
<div> |
||||
|
<canvas ref="canvas" class="container" @mouseup="handleMouseUp" @mousedown="handleMouseDown" @mousemove="handleMouseMove"></canvas> |
||||
|
<!-- <video width="500" height="280" autoplay muted loop> |
||||
|
<source src="./assets/big_buck_bunny.mp4" type="video/mp4" /> |
||||
|
</video> --> |
||||
|
<div class="mpegPlayer" ref="mpegPlayer"></div> |
||||
|
</div> |
||||
|
<div> |
||||
|
<div class="flexBox"> |
||||
|
<label>rtsp流地址:</label> |
||||
|
<a-input type="text" v-model:value="rtspUrl"></a-input> |
||||
|
<a-button @click="open">打开rtsp</a-button> |
||||
|
<a-button @click="close">关闭rtsp</a-button> |
||||
|
</div> |
||||
|
<div v-if="msg">消息:rtsp流{{ msg }}</div> |
||||
|
<a-button type="primary" @click="change(0)"><ApiOutlined />关闭创建</a-button> |
||||
|
<a-button type="primary" @click="change(1)">创建矩形</a-button> |
||||
|
<a-button type="primary" @click="change(2)">创建多边形</a-button> |
||||
|
<a-button type="primary" @click="change(3)">创建标记点</a-button> |
||||
|
<a-button type="primary" @click="change(4)">创建线</a-button> |
||||
|
<a-button type="primary" @click="change(5)">创建圆</a-button> |
||||
|
<!-- <a-button type="primary" @click="toggleLineType()">切换线型-测试</a-button> --> |
||||
|
<br /> |
||||
|
<br /> |
||||
|
<a-button type="primary" @click="zoom(true)"><PlusOutlined />放大</a-button> |
||||
|
<a-button type="primary" @click="zoom(false)"><MinusOutlined />缩小</a-button> |
||||
|
<!-- <a-button type="primary" @click="fitting()">最佳适配比</a-button> --> |
||||
|
<a-button type="primary" @click="onFocus()"><AimOutlined />专注模式</a-button> |
||||
|
<br /> |
||||
|
<br /> |
||||
|
<a-button type="primary" danger @click="clear()"><FormatPainterOutlined />清除绘制</a-button> |
||||
|
<a-button type="primary" danger @click="lock()"><LinkOutlined />锁定/解锁</a-button> |
||||
|
<br /> |
||||
|
<br /> |
||||
|
<a-button type="primary" @click="save()"><FileDoneOutlined />保存</a-button> |
||||
|
</div> |
||||
|
</div> |
||||
|
<div class="right"> |
||||
|
<pre> |
||||
|
1.设置 instance.createType 指定需要创建形状类型。 |
||||
|
|
||||
|
2.创建矩形时,按住鼠标左键拖动完成创建。 |
||||
|
|
||||
|
3.创建多边形时,鼠标左键单击添加点,双击闭合完成创建,Backspace退出创建,Escape退一步删除选择点。 |
||||
|
|
||||
|
4.创建折线时,鼠标左键单击添加点,双击完成创建,Backspace退出创建,Escape退一步删除选择点。 |
||||
|
|
||||
|
5.按住鼠标右键拖动画布。 |
||||
|
|
||||
|
6.鼠标滚轮缩放画布。 |
||||
|
|
||||
|
7.选中形状,Backspace删除。 |
||||
|
</pre |
||||
|
> |
||||
|
</div> |
||||
|
</div> |
||||
|
</template> |
||||
|
|
||||
|
<script lang="ts" setup> |
||||
|
import { onMounted, ref } from 'vue'; |
||||
|
import { |
||||
|
FileDoneOutlined, |
||||
|
FormatPainterOutlined, |
||||
|
LinkOutlined, |
||||
|
PlusOutlined, |
||||
|
MinusOutlined, |
||||
|
ApiOutlined, |
||||
|
AimOutlined, |
||||
|
} from '@ant-design/icons-vue'; |
||||
|
// 标注相关 |
||||
|
import CanvasSelect from 'canvas-select'; |
||||
|
// rtsp视频播放相关 |
||||
|
import MpegPlayer from 'jsmpeg-player'; |
||||
|
const { ipcRenderer } = require('electron'); |
||||
|
// rtsp流地址 |
||||
|
const rtspUrl = ref('rtsp://admin:hk123456@192.168.1.71:554/'); |
||||
|
const mpegPlayer = ref(); |
||||
|
// 消息 |
||||
|
const msg = ref(''); |
||||
|
// 播放容器 |
||||
|
let player: any = null; |
||||
|
//当前canvas实例 |
||||
|
const canvas = ref(null); |
||||
|
// 鼠标位置 |
||||
|
const mouseX = ref(0); |
||||
|
const mouseY = ref(0); |
||||
|
const isRightMouseDown = ref(false); |
||||
|
// |
||||
|
// 开启rtsp播放 |
||||
|
const open = () => { |
||||
|
const res = ipcRenderer.sendSync('openRtsp', rtspUrl.value); |
||||
|
if (res.code === 200) { |
||||
|
player = new MpegPlayer.VideoElement(mpegPlayer.value, res.ws); |
||||
|
} |
||||
|
msg.value = res.msg; |
||||
|
}; |
||||
|
// 关闭rtsp播放 |
||||
|
const close = () => { |
||||
|
const res = ipcRenderer.sendSync('closeRtsp', rtspUrl.value); |
||||
|
msg.value = res.msg; |
||||
|
}; |
||||
|
|
||||
|
// 导入静态图片 |
||||
|
const hideUrl = new URL('./assets/hide.png', import.meta.url).href; |
||||
|
//标注实例 |
||||
|
let instance: any = ref(null); |
||||
|
//图形标注列表 |
||||
|
const option: any = ref([]); |
||||
|
onMounted(() => { |
||||
|
// 载入绘图数据 |
||||
|
option.value = JSON.parse(localStorage.getItem('canvasData')!); |
||||
|
// 创建实例 |
||||
|
instance = new CanvasSelect('.container', hideUrl); |
||||
|
// 标签最大长度 |
||||
|
instance.labelMaxLen = 10; |
||||
|
// 禁用滚动缩放 |
||||
|
instance.scrollZoom = false; |
||||
|
// 图形数据赋值到实例 |
||||
|
instance.setData(option.value); |
||||
|
// 形状边线宽度 |
||||
|
instance.lineWidth = 2; |
||||
|
// 标签字体 |
||||
|
instance.labelFont = '12px Arial'; |
||||
|
// 标签填充颜色 |
||||
|
instance.labelFillStyle = '#fa4545'; |
||||
|
// 标签文字颜色 |
||||
|
instance.textFillStyle = '#fff'; |
||||
|
// 控制点半径 |
||||
|
instance.ctrlRadius = 4; |
||||
|
// 图片加载完成 |
||||
|
instance.on('load', (src: any) => { |
||||
|
console.log('image load', src); |
||||
|
}); |
||||
|
|
||||
|
// 添加 |
||||
|
instance.on('add', (info: any) => { |
||||
|
// 添加默认标签 |
||||
|
switch (instance.createType) { |
||||
|
case 1: |
||||
|
info.label = '矩形防区'; |
||||
|
break; |
||||
|
case 2: |
||||
|
info.label = '多边形防区'; |
||||
|
break; |
||||
|
case 3: |
||||
|
info.label = '标记点位'; |
||||
|
break; |
||||
|
case 4: |
||||
|
info.label = '报警界线'; |
||||
|
break; |
||||
|
case 5: |
||||
|
info.label = '圆形防区'; |
||||
|
break; |
||||
|
default: |
||||
|
info.label = '未定义'; |
||||
|
} |
||||
|
// 更新画布 |
||||
|
instance.update(); |
||||
|
}); |
||||
|
// 删除 |
||||
|
instance.on('delete', (info: any) => { |
||||
|
console.log('delete', info); |
||||
|
}); |
||||
|
// 选中 |
||||
|
instance.on('select', (shape: any) => { |
||||
|
console.log('select', shape); |
||||
|
}); |
||||
|
// 更新 |
||||
|
instance.on('updated', (result: any) => { |
||||
|
// console.log('标注结果', result); |
||||
|
}); |
||||
|
}); |
||||
|
|
||||
|
// 获取当前鼠标在画布上的位置 |
||||
|
function handleMouseMove(e) { |
||||
|
const rect = canvas.value.getBoundingClientRect(); |
||||
|
mouseX.value = e.clientX - rect.left; |
||||
|
mouseY.value = e.clientY - rect.top; |
||||
|
if (isRightMouseDown.value) { |
||||
|
// 在这里处理鼠标右键按住移动的逻辑 |
||||
|
// console.log('鼠标右键按住移动'); |
||||
|
// 可以根据需要执行其他操作 |
||||
|
console.log(instance); |
||||
|
} |
||||
|
} |
||||
|
// 鼠标抬起 |
||||
|
function handleMouseUp(e) { |
||||
|
if (e.button === 2) { |
||||
|
isRightMouseDown.value = false; |
||||
|
} |
||||
|
} |
||||
|
// 鼠标按下 |
||||
|
function handleMouseDown(e) { |
||||
|
if (e.button === 2) { |
||||
|
isRightMouseDown.value = true; |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
// 选择绘制工具 |
||||
|
function change(num: any) { |
||||
|
instance.createType = num; |
||||
|
} |
||||
|
// 放大缩小画布 |
||||
|
function zoom(type: any) { |
||||
|
instance.setScale(type); |
||||
|
} |
||||
|
// 适配 |
||||
|
// function fitting() { |
||||
|
// instance.fitZoom(); |
||||
|
// } |
||||
|
// 专注模式 |
||||
|
function onFocus() { |
||||
|
instance.setFocusMode(!instance.focusMode); |
||||
|
} |
||||
|
//清除标注数据 |
||||
|
function clear() { |
||||
|
instance.setData([]); |
||||
|
} |
||||
|
// 锁定/解锁画布 |
||||
|
function lock() { |
||||
|
instance.lock = !instance.lock; |
||||
|
} |
||||
|
// 保存数据 |
||||
|
function save() { |
||||
|
// 保存绘制数据,用于回显 |
||||
|
// 清除所有激活状态 |
||||
|
instance.dataset.forEach((item) => { |
||||
|
item.active = false; |
||||
|
}); |
||||
|
console.log(JSON.stringify(instance.dataset)); |
||||
|
// 暂存数据到本地 |
||||
|
localStorage.setItem('canvasData', JSON.stringify(instance.dataset)); |
||||
|
} |
||||
|
</script> |
||||
|
<style scoped> |
||||
|
.box { |
||||
|
display: flex; |
||||
|
margin: 10px; |
||||
|
position: relative; |
||||
|
} |
||||
|
.container { |
||||
|
width: 800px; |
||||
|
height: 480px; |
||||
|
position: absolute; |
||||
|
z-index: 999; |
||||
|
left: 0; |
||||
|
top: 0; |
||||
|
} |
||||
|
button { |
||||
|
margin-right: 3px; |
||||
|
} |
||||
|
|
||||
|
.flexBox { |
||||
|
display: flex; |
||||
|
height: 50px; |
||||
|
margin-top: 20px; |
||||
|
} |
||||
|
.flexBox input { |
||||
|
height: 30px; |
||||
|
width: 400px; |
||||
|
box-sizing: border-box; |
||||
|
padding-left: 8px; |
||||
|
} |
||||
|
.flexBox button { |
||||
|
height: 30px; |
||||
|
padding: 0 12px; |
||||
|
} |
||||
|
.mpegPlayer { |
||||
|
width: 800px; |
||||
|
height: 480px; |
||||
|
background: #000; |
||||
|
} |
||||
|
</style> |
Binary file not shown.
After Width: | Height: | Size: 1.6 KiB |
Loading…
Reference in new issue