在工业生产安全管理系统中,警戒区域监控是一个常见且重要的功能需求。通过划定特定区域并监控人员或物体的闯入行为,可以有效预防安全事故的发生。本文将详细介绍如何基于Vue.js和Element UI框架,实现一个后台管理系统中的摄像头警戒区域绘制功能。
这个功能的核心是在摄像头实时画面或预览图上,允许管理员通过鼠标交互绘制多个矩形警戒区域。系统会记录这些区域的坐标信息,当有物体进入这些区域时触发报警机制。相比传统的固定区域设置,这种可视化绘制方式更加直观和灵活。
本项目选择了Vue.js作为前端框架,主要基于以下考虑:
UI框架选择了Element UI,原因包括:
整个功能模块的架构可以分为以下几个部分:
这种分层架构使得各功能模块职责清晰,便于后续扩展和维护。
设备选择采用了四级联动下拉菜单(工厂→车间→点位→设备),这种设计符合实际生产环境中的物理层级关系。关键实现代码如下:
javascript复制// 获取车间列表
getWorkShop() {
this.workShopList = [];
workShopSelect({
factoryId: this.form.factoryId,
pointId: this.form.pointId
}).then(res => {
this.workShopList = res.data || [];
})
}
当用户选择设备后,系统会加载该设备的预览图像:
javascript复制// 选择设备带出图片
var img = this.equipmentList.find(i => i.key == this.form.equId);
this.$set(this.form, 'imageSrc', img ? img.initCover : '');
这里使用了Vue的$set方法来确保响应式更新,避免直接赋值导致的响应性问题。
在图像上叠加Canvas层是实现区域绘制的关键技术。主要实现步骤如下:
offsetX和offsetY获取鼠标在Canvas中的相对坐标。关键代码片段:
html复制<div style="position: relative;height: 380px;margin-top: 10px;">
<img :src="form.imageSrc" :width="canvasWidth" :height="canvasHeight"
style="position: absolute; top: 0; left: 0;" />
<canvas ref="canvas" :width="canvasWidth" :height="canvasHeight"
@mousedown="onMouseDown" @mouseup="onMouseUp" @mousemove="onMouseMove"
:style="{ border: '1px solid black', position: 'absolute', top: '0', left: '0', cursor: view ? 'default' : 'crosshair', pointerEvents: view ? 'none' : 'auto' }"></canvas>
</div>
系统支持绘制四边形区域,并允许拖动顶点进行编辑。实现原理如下:
Math.hypot()计算鼠标位置与各点的距离,判断是否选中某个点。核心绘制函数:
javascript复制drawPolygon(ctx, points, color) {
ctx.beginPath();
ctx.moveTo(points[0].x, points[0].y);
points.forEach((point) => {
ctx.lineTo(point.x, point.y);
});
ctx.closePath();
ctx.strokeStyle = color;
ctx.stroke();
// 绘制顶点
points.forEach((point, index) => {
ctx.fillStyle = this.selectedPointIndex === index ? "red" : "green";
ctx.beginPath();
ctx.arc(point.x, point.y, 5, 0, Math.PI * 2);
ctx.fill();
});
}
绘制的区域坐标需要转换为JSON字符串保存到后端:
javascript复制const coordinates = this.polygons.map(polygon =>
polygon.map(point => ({ x: point.x, y: point.y })));
this.form.points = JSON.stringify(coordinates);
这种序列化方式保留了完整的几何信息,便于后续的解析和处理。
使用Element UI的表单验证功能确保必填字段:
javascript复制rules: {
name: [
{ required: true, message: "方案名称不能为空", trigger: "blur" }
],
workshopId: [
{ required: true, message: "请选择所在车间", trigger: "change" }
],
// 其他字段验证规则...
}
提交前会检查是否至少绘制了一个区域:
javascript复制if (coordinates.length > 0) {
// 提交数据
} else {
this.$modal.msgWarning("请至少绘制出一个区域");
}
问题:Canvas坐标与实际图像坐标的对应关系可能出现偏差。
解决方案:
问题:当绘制大量区域时可能出现卡顿。
解决方案:
问题:更换设备图片后,原有区域坐标可能不再适用。
解决方案:
在实际项目中实现这类功能时,有几个关键点值得注意:
坐标系的统一:确保前端绘制坐标与后端分析坐标使用同一基准,否则报警检测会不准确。我们曾经因为这个问题导致大量误报,后来通过在前端保存原始图像分辨率信息解决了这个问题。
绘制体验优化:最初版本要求用户必须按顺序点击四个点,用户体验很差。后来改为记录任意四个点后自动排序,大大提高了易用性。
数据验证:一定要对前端传回的坐标数据进行严格验证,防止非法数据导致后端处理异常。我们添加了坐标范围检查(必须在图像尺寸内)和凸四边形验证等规则。
移动端适配:如果需要在移动设备上使用,要考虑触摸事件的处理和更粗大的控制点,这与桌面版的实现有很大不同。
这个功能看似简单,但在实际工业环境中使用时,需要考虑各种边界情况和异常处理。建议在正式上线前进行充分的测试,特别是各种异常操作场景的测试。