以下是一个完整的案例 只要加上自己图片的地址 就可以直接在页面上用了
有任何问题可以评论,看到会及时回复
<template>
<div>
<!-- 撤回按钮 -->
<el-button type="primary" size="mini" @click="undo">撤回</el-button>{{ polygonsConvent }}
<!-- 保存图片按钮 -->
<!-- <el-button type="primary" size="mini" @click="saveImage">保存图片</el-button> -->
<!-- 颜色选择器 -->
<!-- <input type="color" v-model="polygonColor" /> -->
<!-- 创建一个容器来放置画布 -->
<div style="width: 1500px; height: 800px; overflow: hidden; overflow:auto">
<!-- 在容器内部创建一个画布,并设置其样式 -->
<canvas style="object-fit: cover;" ref="canvas" @mousedown="startDrawing" @mousemove="drawLine" @mouseup="endDrawing"></canvas>
</div>
</div>
</template>
<script>
export default {
data() {
return {
// 画布和上下文
canvas: null,
context: null,
// 点和多边形
points: [], // 存储当前正在绘制的多边形的点
polygons: [], // 存储已完成的多边形
polygonsConvent:[],//存储已换算后的多边形坐标
// 多边形的颜色和吸附距离
polygonColor: '#FF0000',
snapDistance: 20,
// 原始图片和绘制状态
originalImage: null,
drawing: false,
imageUrl:'自己图片的地址',
};
},
mounted() {
// 获取画布和上下文,并加载图片
this.canvas = this.$refs.canvas;
this.context = this.canvas.getContext('2d');
this.loadImage();
},
methods: {
//把已有的坐标自动显示在图片上 如果有需求的话 可以直接调用这个方法 this.loadImageshow()
loadImageshow() {
// 创建图片对象,加载图片,加载完成后绘制到画布上
const image = new Image();
image.onload = () => {
this.originalImage = image;
// 将图片尺寸缩小40%
this.canvas.width = image.width * 0.4;
this.canvas.height = image.height * 0.4;
this.context.drawImage(image, 0, 0, this.canvas.width, this.canvas.height);
// 图片加载完成后显示多边形
this.showPolygonsOnImage(this.iceArea);//this.iceArea自己要显示在图片上的坐标 例子:[ [ [ 753, 383 ], [ 755, 578 ], [ 1315, 580 ], [ 1265, 308 ] ] ]
};
image.src = this.imageUrl;
},
// 绘制多边形
drawPolygon(polygon) {
// 绘制多边形线条
this.context.beginPath();
this.context.moveTo(polygon[0][0], polygon[0][1]);
for (let i = 1; i < polygon.length; i++) {
this.context.lineTo(polygon[i][0], polygon[i][1]);
}
this.context.closePath();
this.context.strokeStyle = this.polygonColor;
this.context.lineWidth = 2;
this.context.stroke();
},
// 在图片加载后显示多边形
showPolygonsOnImage(polygons) {
polygons.forEach(polygon => {
const scaledPolygon = polygon.map(point => [point[0] * 0.4, point[1] * 0.4]);
this.drawPolygon(scaledPolygon);
});
},
//鼠标手动画框 调用这个方法
loadImage() {
// 创建图片对象,加载图片,加载完成后绘制到画布上
const image = new Image();
image.onload = () => {
this.originalImage = image;
// 将图片尺寸缩小40%
this.canvas.width = image.width * 0.4;
this.canvas.height = image.height * 0.4;
this.context.drawImage(image, 0, 0, this.canvas.width, this.canvas.height);
};
image.src = this.imageUrl;
},
startDrawing(event) {
// 开始绘制,记录鼠标位置,并绘制点和线
this.drawing = true;
const x = event.clientX - this.canvas.getBoundingClientRect().left;
const y = event.clientY - this.canvas.getBoundingClientRect().top;
this.points.push([x, y]);
this.drawPoints();
this.drawLines();
},
drawLine(event) {
// 绘制线
if (!this.drawing) return;
if (this.points.length < 1) return;
const x = event.clientX - this.canvas.getBoundingClientRect().left;
const y = event.clientY - this.canvas.getBoundingClientRect().top;
this.context.clearRect(0, 0, this.canvas.width, this.canvas.height);
this.context.drawImage(this.originalImage, 0, 0, this.canvas.width, this.canvas.height);
this.drawPoints();
this.drawLines();
// 绘制当前点和之前所有点之间的线
for (let i = 1; i < this.points.length; i++) {
this.context.beginPath();
this.context.moveTo(this.points[i - 1][0], this.points[i - 1][1]);
this.context.lineTo(this.points[i][0], this.points[i][1]);
this.context.strokeStyle = this.polygonColor;
this.context.lineWidth = 2;
this.context.stroke();
}
// 绘制当前点和最后一个点之间的线
this.context.beginPath();
this.context.moveTo(this.points[this.points.length - 1][0], this.points[this.points.length - 1][1]);
this.context.lineTo(x, y);
this.context.strokeStyle = this.polygonColor;
this.context.lineWidth = 2;
this.context.stroke();
},
drawPoints() {
// 绘制所有的点
this.points.forEach(point => {
this.context.beginPath();
this.context.arc(point[0], point[1], 3, 0, 2 * Math.PI);
this.context.fillStyle = this.polygonColor;
this.context.fill();
});
},
drawLines() {
// 绘制所有的多边形线条
this.polygons.forEach(polygon => {
this.context.beginPath();
this.context.moveTo(polygon[0][0], polygon[0][1]);
polygon.forEach(point => {
this.context.lineTo(point[0], point[1]);
});
this.context.closePath();
this.context.strokeStyle = this.polygonColor;
this.context.lineWidth = 2;
this.context.stroke();
});
},
endDrawing() {
// 结束绘制
if (!this.drawing) return;
if (this.points.length > 1) {
const firstPoint = this.points[0];
const lastPoint = this.points[this.points.length - 1];
const distance = Math.sqrt((firstPoint[0] - lastPoint[0]) ** 2 + (firstPoint[1] - lastPoint[1]) ** 2);
if (distance <= this.snapDistance && this.points.length > 2) {
console.log([...this.points.slice(0, -1)])
// 计算缩放比例
const scale = 1 / 0.4; // 缩小了40%,所以放大比例是 1 / 0.4
// 将多边形的每个点的坐标乘以比例因子,实现100%换算
const scaledPolygon = this.points.slice(0, -1).map(point => [Math.round(point[0] * scale), Math.round(point[1] * scale)]);
console.log(scaledPolygon)
this.polygons.push([...this.points.slice(0, -1)]); // 将当前多边形添加到多边形数组中
this.polygonsConvent.push(scaledPolygon)
this.points = []; // 清空当前绘制的多边形的点数组
this.drawing = false;
this.redrawPolygons();
}
}
},
undo() {
// 撤回操作
if (this.polygons.length > 0) {
this.polygons.pop(); // 删除最后一个多边形
this.polygonsConvent.pop();
this.redrawPolygons();
}
},
redrawPolygons() {
// 重新绘制多边形
this.context.clearRect(0, 0, this.canvas.width, this.canvas.height);
this.context.drawImage(this.originalImage, 0, 0, this.canvas.width, this.canvas.height);
this.polygons.forEach(polygon => {
this.context.beginPath();
this.context.moveTo(polygon[0][0], polygon[0][1]);
polygon.forEach(point => {
this.context.lineTo(point[0], point[1]);
});
this.context.closePath();
this.context.strokeStyle = this.polygonColor;
this.context.lineWidth = 2;
this.context.stroke();
});
},
saveImage() {
// 保存绘制的图片
const dataUrl = this.canvas.toDataURL('image/png');
const link = document.createElement('a');
link.href = dataUrl;
link.download = 'drawn_image.png';
link.click();
},
},
};
</script>
<style>
canvas {
border: 1px solid #000;
}
</style>