使用canvas绘制通过多边形标注区域
AI视频项目中需要分析图片,需要前台绘制区域,后端获取坐标然后识别图像,通过canvas
获取点然后连线绘图
HEML代码段
<div class="areaDrawing">
<img src="@/assets/images/snapPhotos.png" />
<canvas ref="canvas" style="position: absolute; top: 0; left: 0;" :width="canvasWidth"
:height="canvasHeight"></canvas>
</div>
CSS代码段
.areaDrawing {
position: relative;
width: 400px; // 绘图区域宽度
height: 300px; // 绘图区域高度
img {
position: absolute;
top: 0;
left: 0;
height: 100%;
width: 100%;
}
}
script代码段
<script>
// 脚本开始
export default {
data() {
return {
canvasWidth: 400, // 画布的宽度
canvasHeight: 300, // 画布的高度
imageSrc: 'your_image_url_here', // 图像的URL地址
context: null, // 画布上下文
points: [], // 用于存储点的数组
isDragging: false, // 是否正在拖拽
draggingIndex: -1, // 当前拖拽的点的索引
Drawing: false,//控制绘制
};
},
methods: {
// 处理点击事件,用于添加新点
handleCanvasClick(event) {
console.log(this.points.length, 'this.points.length');
// 检查是否开启绘制
if (!this.Drawing || this.points.length >= 4) {
return;
}
// 获取点击点的坐标
const rect = this.$refs.canvas.getBoundingClientRect();
const x = event.clientX - rect.left;
const y = event.clientY - rect.top;
// 检查是否有重复点
const isDuplicate = this.points.some(point => {
return Math.abs(point.x - x) < 5 && Math.abs(point.y - y) < 5;
});
// 如果没有重复点,则添加新点并重新绘制
if (!isDuplicate) {
this.points.push({ x, y });
this.redraw();
}
// 如果点的数量大于等于4个,则绘制多边形
if (this.points.length >= 4) {
this.drawPolygon(this.points);
}
},
// 处理鼠标按下事件
handleMouseDown(event) {
if (this.Drawing) {
return
}
// 获取鼠标按下点的坐标
const rect = this.$refs.canvas.getBoundingClientRect();
const x = event.clientX - rect.left;
const y = event.clientY - rect.top;
// 查找当前拖拽的点的索引
this.draggingIndex = this.points.findIndex(point => {
return Math.abs(point.x - x) < 5 && Math.abs(point.y - y) < 5;
});
// 如果存在拖拽的点,则设置拖拽状态为true
if (this.draggingIndex !== -1) {
this.isDragging = true;
}
},
// 处理鼠标移动事件
handleMouseMove(event) {
// 如果正在拖拽,则更新当前拖拽点的坐标并重新绘制
if (this.isDragging) {
const rect = this.$refs.canvas.getBoundingClientRect();
const x = event.clientX - rect.left;
const y = event.clientY - rect.top;
this.points[this.draggingIndex].x = x;
this.points[this.draggingIndex].y = y;
this.redraw();
}
},
// 处理鼠标释放事件
handleMouseUp() {
// 重置拖拽状态和拖拽点的索引
this.isDragging = false;
this.draggingIndex = -1;
},
// 绘制点
drawPoint(x, y) {
this.context.beginPath();
this.context.arc(x, y, 5, 0, 2 * Math.PI, false);
this.context.fillStyle = 'blue';
this.context.fill();
this.context.lineWidth = 1;
this.context.strokeStyle = 'blue';
this.context.stroke();
},
// 重新绘制画布
redraw() {
// 清空画布
this.context.clearRect(0, 0, this.canvasWidth, this.canvasHeight);
// 绘制多边形
this.drawPolygon(this.points);
// 绘制所有点,并连接相邻点
this.points.forEach((point, index) => {
this.drawPoint(point.x, point.y);
if (index > 0) {
this.context.beginPath();
this.context.moveTo(this.points[index - 1].x, this.points[index - 1].y);
this.context.lineTo(point.x, point.y);
this.context.strokeStyle = 'blue';
this.context.lineWidth = 1;
this.context.stroke();
}
});
// 连接第一个点和最后一个点,形成闭合的多边形
if (this.points.length > 3) {
this.context.beginPath();
this.context.moveTo(this.points[this.points.length - 1].x, this.points[this.points.length - 1].y);
this.context.lineTo(this.points[0].x, this.points[0].y);
this.context.strokeStyle = 'blue';
this.context.lineWidth = 1;
this.context.stroke();
}
},
// 绘制多边形
drawPolygon(points) {
if (points.length >= 2) {
this.context.beginPath();
this.context.moveTo(points[0].x, points[0].y);
for (let i = 1; i < points.length; i++) {
this.context.lineTo(points[i].x, points[i].y);
}
if (points.length === 4) {
this.context.closePath();
this.context.strokeStyle = 'red';
this.context.lineWidth = 2;
this.context.stroke();
}
}
},
// 动画方法,用于拖拽时重新绘制画布
animate() {
if (this.isDragging) {
this.redraw();
requestAnimationFrame(this.animate);
}
},
//开始绘制
handleDrawing() {
this.Drawing = true;
},
//绘制微调
resetDrawing() {
this.Drawing = false;
},
//清除绘制
clearDrawing() {
this.points.length = 0;
this.redraw()
},
},
mounted() {
// 获取画布上下文
this.context = this.$refs.canvas.getContext('2d');
// 添加事件监听器
this.$refs.canvas.addEventListener('click', this.handleCanvasClick);
this.$refs.canvas.addEventListener('mousedown', this.handleMouseDown);
this.$refs.canvas.addEventListener('mousemove', this.handleMouseMove);
this.$refs.canvas.addEventListener('mouseup', this.handleMouseUp);
this.$refs.canvas.addEventListener('mouseleave', this.handleMouseUp);
// 绑定动画方法的上下文
this.animate = this.animate.bind(this);
},
};
// 脚本结束
</script>