vue项目需要在图片进行画框操作,用来进行重点标注,这里使用canvas来实现。
实现代码
<template>
<div class="test" style="background-color: burlywood; display: flex">
<canvas
id="myCanvas"
ref="myCanvas"
width="1100"
height="500"
@mousedown="mousedown($event)"
@dblclick="handleDBClick"
@mousemove="mousemove"
>
</canvas>
</div>
</template>
<script>
export default {
name: "DefectRect",
data() {
return {
ctx: "", //dom节点
canvas: null,
tempPointArr: [], //临时存储每次点击的位置
moveStatus: false,
savePointArr: [], //保存每次点击的位置
};
},
mounted() {
this.canvas = this.$refs.myCanvas;
this.ctx = this.canvas.getContext("2d");
},
methods: {
// 放下鼠标
mousedown(e) {
clearTimeout(this.timer);
this.moveStatus = true;
this.timer = setTimeout(() => {
// 每次点击,保存点击的位置
this.tempPointArr.push([e.offsetX, e.offsetY]);
// 绘制矩形小点
this.ctx.fillStyle = "#FF0000";
this.ctx.fillRect(e.offsetX - 0.5, e.offsetY - 0.5, 1, 1);
if (this.tempPointArr.length <= 1) return;
// 设置线宽
this.ctx.lineWidth = 2;
// 连线
this.ctx.beginPath();
this.ctx.strokeStyle = "#FF0000";
// 找到需要连线的那个点
this.ctx.moveTo(
this.tempPointArr[this.tempPointArr.length - 2][0],
this.tempPointArr[this.tempPointArr.length - 2][1]
);
// 画线
this.ctx.lineTo(
this.tempPointArr[this.tempPointArr.length - 1][0],
this.tempPointArr[this.tempPointArr.length - 1][1]
);
this.ctx.stroke();
}, 200);
},
// 移动鼠标,实现线跟随鼠标移动
mousemove(e) {
if (this.moveStatus) {
let point = [e.offsetX, e.offsetY];
// 先清除每次移动画出的线
if (this.tempPointArr.length < 1) return;
this.clear();
// // 将点过的点之前的连线回显出来
this.echoTempPoint(this.tempPointArr, false);
this.ctx.fillStyle = "#FF0000";
this.ctx.lineWidth = 2;
// 连线
this.ctx.beginPath();
this.ctx.strokeStyle = "#FF0000";
// 找到需要连线的那个点
this.ctx.moveTo(
this.tempPointArr[this.tempPointArr.length - 1][0],
this.tempPointArr[this.tempPointArr.length - 1][1]
);
this.ctx.lineTo(point[0], point[1]);
this.ctx.stroke();
}
},
// 回显之前画的点之间的连线
echoTempPoint(cur, status) {
for (let i = 0; i < cur.length; i++) {
// 绘制矩形小点
this.ctx.fillStyle = "#FF0000";
this.ctx.fillRect(cur[i][0] - 0.5, cur[i][1] - 0.5, 1, 1);
this.ctx.lineWidth = 2;
// 连线
this.ctx.beginPath();
this.ctx.strokeStyle = "#FF0000";
if (i !== 0) {
// 找到需要连线的那个点
this.ctx.moveTo(cur[i - 1][0], cur[i - 1][1]);
this.ctx.lineTo(cur[i][0], cur[i][1]);
}
// status判断回显时是否连接最后一个点和第一个点
if (status) {
if (i == cur.length - 1) {
this.ctx.moveTo(cur[i][0], cur[i][1]);
this.ctx.lineTo(cur[0][0], cur[0][1]);
}
}
this.ctx.stroke();
}
},
//清除画布
clear() {
this.ctx.clearRect(0, 0, this.canvas.width, this.canvas.height);
},
//双击保存数据,并链接最后一个点和第一个点
handleDBClick() {
clearTimeout(this.timer);
if (this.tempPointArr.length <= 2) {
this.$message.warning("至少需要3个点");
} else {
this.savePointArr.push(this.tempPointArr);
this.ctx.moveTo(
this.tempPointArr[this.tempPointArr.length - 1][0],
this.tempPointArr[this.tempPointArr.length - 1][1]
);
this.ctx.lineTo(this.tempPointArr[0][0], this.tempPointArr[0][1]);
this.ctx.stroke();
this.moveStatus = false;
this.tempPointArr = [];
}
},
},
};
</script>
<style lang="scss" scoped>
.test {
display: flex;
justify-content: center;
align-items: center;
flex-wrap: nowrap;
flex-direction: row;
align-content: flex-start;
}
#myCanvas {
position: relative;
background: url("./assets/img.jpg") no-repeat;
background-size: 100% 100%;
}
</style>
项目应用
vue3 数据可视化大屏 视频监控智能分析系统